home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / macgambit-20-compiler-src-p2 / Interp⁄Comp (.scm) / target-m68000-1.scm < prev    next >
Encoding:
Text File  |  1994-07-26  |  134.4 KB  |  3,809 lines  |  [TEXT/gamI]

  1. ;==============================================================================
  2.  
  3. ; file: "target-m68000-1.scm"
  4.  
  5. ;------------------------------------------------------------------------------
  6. ;
  7. ; Target machine abstraction (for M68000):
  8.  
  9. ; The virtual machine implementation is a mapping of PVM instructions
  10. ; and operands to M68000 instructions and operands.  The mapping of
  11. ; operands is fairly simple because M68000 operands form a superset of
  12. ; PVM operands.  PVM registers are mapped to M68000 registers, the PVM stack
  13. ; is implemented with the M68000's stack and global variables are
  14. ; implemented by an array of objects.
  15. ;
  16. ; The M68000's registers are dedicated as follows:
  17. ;
  18. ; D0      temporary register (also used as the argument count register)
  19. ; D1..D4  PVM registers 1 to 4
  20. ; D5      interrupt countdown timer (low 16 bits)
  21. ; D6      always = () = 11101111111011111110111111101111 (placeholder mask)
  22. ; D7      always = #f = 11110111111101111111011111110111 (pair mask)
  23. ;
  24. ; A0      PVM register 0 (mostly used to hold the return address)
  25. ; A1..A2  temporary registers (to implement PVM instructions)
  26. ; A3      heap allocation pointer (grows downwards)
  27. ; A4      lazy task queue tail pointer (grows downwards)
  28. ; A5      always = pointer to the processor's state (local variables)
  29. ; A6      always = pointer to the global variable table and code area
  30. ; A7      stack pointer (grows downwards)
  31.  
  32. ;------------------------------------------------------------------------------
  33.  
  34. (define (begin! info-port targ) ; initialize package
  35.  
  36.   (set! return-reg (make-reg 0))
  37.  
  38.   (target-end!-set!         targ end!)
  39.   (target-dump-set!         targ dump)
  40.   (target-nb-regs-set!      targ nb-pvm-regs)
  41.   (target-prim-info-set!    targ prim-info)
  42.   (target-label-info-set!   targ label-info)
  43.   (target-jump-info-set!    targ jump-info)
  44.   (target-proc-result-set!  targ (make-reg 1))
  45.   (target-task-return-set!  targ return-reg)
  46.  
  47.   (set! *info-port* info-port)
  48.  
  49.   '())
  50.  
  51. (define (end!) ; finalize package
  52.   '())
  53.  
  54. (define *info-port* '())
  55.  
  56. ;------------------------------------------------------------------------------
  57. ;
  58. ; Usage of registers:
  59.  
  60. (define nb-pvm-regs 5) ; Number of registers in the virtual machine.
  61.  
  62. (define nb-arg-regs 3) ; Number of registers used to pass arguments.
  63.  
  64. ;------------------------------------------------------------------------------
  65. ;
  66. ; Size of an object pointer
  67.  
  68. (define pointer-size 4)
  69.  
  70. ;------------------------------------------------------------------------------
  71. ;
  72. ; Primitive procedure database:
  73.  
  74. (define prim-proc-table
  75.   (map (lambda (x)
  76.          (cons (string->canonical-symbol (car x))
  77.                (apply make-proc-obj (car x) #t #f (cdr x))))
  78.        prim-procs))
  79.  
  80. (define (prim-info name)
  81.   (let ((x (assq name prim-proc-table)))
  82.     (if x (cdr x) #f)))
  83.  
  84. (define (get-prim-info name)
  85.   (let ((proc (prim-info (string->canonical-symbol name))))
  86.     (if proc
  87.       proc
  88.       (compiler-internal-error
  89.         "get-prim-info, unknown primitive:" name))))
  90.  
  91. ;------------------------------------------------------------------------------
  92. ;
  93. ; Procedure calling convention:
  94.  
  95. (define (label-info min-args nb-parms rest? closed?)
  96.  
  97. ;  * return address is in reg(0)
  98. ;
  99. ;  * if nb-parms <= nb-arg-regs,
  100. ;
  101. ;      then, parameter `n' is in reg(n)
  102. ;
  103. ;      else, the first `m' = nb-parms - nb-arg-regs
  104. ;            parameters will be on the stack and parameter `n' is in
  105. ;
  106. ;            reg(n - m), if n > m
  107. ;            or else in stk(frame_size + n - m)
  108. ;
  109. ;  * if `CLOSED' is present, reg(nb-arg-regs + 1) contains a pointer to the
  110. ;    closure object
  111. ;
  112. ; for example, if we assume that nb-arg-regs = 3, then after the
  113. ; instruction LABEL(1,2,PROC,5):
  114. ;
  115. ;   reg(0) = return address
  116. ;   stk(1) = parameter 1
  117. ;   stk(2) = parameter 2
  118. ;   reg(1) = parameter 3
  119. ;   reg(2) = parameter 4
  120. ;   reg(3) = parameter 5
  121.  
  122.   (let ((nb-stacked (max 0 (- nb-parms nb-arg-regs))))
  123.  
  124.     (define (location-of-parms i)
  125.       (if (> i nb-parms)
  126.         '()
  127.         (cons (cons i
  128.                     (if (> i nb-stacked)
  129.                       (make-reg (- i nb-stacked))
  130.                       (make-stk i)))
  131.               (location-of-parms (+ i 1)))))
  132.  
  133.     (let ((x (cons (cons 'return 0) (location-of-parms 1))))
  134.       (make-pcontext nb-stacked
  135.         (if closed?
  136.           (cons (cons 'closure-env (make-reg (+ nb-arg-regs 1))) x)
  137.           x)))))
  138.  
  139. (define (jump-info nb-args)
  140.  
  141. ;  * the return address is passed in reg(0)
  142. ;
  143. ;  * if nb-args <= nb-arg-regs,
  144. ;
  145. ;      then, argument `n' is in reg(n)
  146. ;
  147. ;      else, `m' = nb-args - nb-arg-regs arguments are passed
  148. ;            on the stack and argument `n' is in
  149. ;
  150. ;            reg(n - m), if n > m
  151. ;            or else in stk(frame_size + n - m) if n <= m
  152.  
  153.   (let ((nb-stacked (max 0 (- nb-args nb-arg-regs))))
  154.  
  155.     (define (location-of-args i)
  156.       (if (> i nb-args)
  157.         '()
  158.         (cons (cons i
  159.                     (if (> i nb-stacked)
  160.                       (make-reg (- i nb-stacked))
  161.                       (make-stk i)))
  162.               (location-of-args (+ i 1)))))
  163.  
  164.     (make-pcontext nb-stacked
  165.                    (cons (cons 'return (make-reg 0))
  166.                          (location-of-args 1)))))
  167.  
  168. (define (closed-var-offset i)
  169.  
  170. ; a closure looks like:
  171. ;
  172. ;      _____________________
  173. ;     |__length__|___JSR____|          | high
  174. ;     |_____________________| code ptr |
  175. ;     |_____________________| var 1    V
  176. ;     |_____________________| ...
  177. ;     |_____________________| var N
  178. ;      <----- 32 bits ----->
  179.  
  180.   (+ (* i pointer-size) 2))
  181.  
  182. ;------------------------------------------------------------------------------
  183. ;
  184. ; Translation of PVM instructions into target machine instructions:
  185.  
  186. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  187.  
  188. (define (dump proc filename options)
  189.  
  190.   (if *info-port*
  191.     (begin
  192.       (display "Dumping:" *info-port*)
  193.       (newline *info-port*)))
  194.  
  195.   (set! ofile-asm?   (memq 'ASM   options))
  196.   (set! ofile-stats? (memq 'STATS options))
  197.   (set! debug-info?  (memq 'DEBUG options))
  198.  
  199.   (set! object-queue (queue-empty))
  200.   (set! objects-dumped (queue-empty))
  201.  
  202.   (ofile.begin! filename add-object)
  203.  
  204.   (queue-put! object-queue proc)
  205.   (queue-put! objects-dumped proc)
  206.  
  207.   (let loop ((index 0))
  208.     (if (not (queue-empty? object-queue))
  209.       (let ((obj (queue-get! object-queue)))
  210.  
  211.         (dump-object obj index)
  212.  
  213.         (loop (+ index 1)))))
  214.  
  215.   (ofile.end!)
  216.  
  217.   (if *info-port*
  218.     (newline *info-port*))
  219.  
  220.   (set! object-queue '())
  221.   (set! objects-dumped '()))
  222.  
  223. (define debug-info? '())
  224. (define object-queue '())
  225. (define objects-dumped '())
  226.  
  227. ;------------------------------------------------------------------------------
  228.  
  229. (define (add-object obj)
  230.   (if (and (proc-obj? obj) (not (proc-obj-code obj)))
  231.     #f
  232.     (let ((n (pos-in-list obj (queue->list objects-dumped))))
  233.       (if n
  234.         n
  235.         (let ((m (length (queue->list objects-dumped))))
  236.           (queue-put! objects-dumped obj)
  237.           (queue-put! object-queue obj)
  238.           m)))))
  239.  
  240. ;------------------------------------------------------------------------------
  241.  
  242. (define (dump-object obj index)
  243.  
  244.   (ofile-line "|------------------------------------------------------")
  245.  
  246.   (case (obj-type obj)
  247.     ((PAIR)        (dump-PAIR obj))
  248.     ((SUBTYPED)    (case (obj-subtype obj)
  249.                      ((VECTOR) (dump-VECTOR obj))
  250.                      ((SYMBOL) (dump-SYMBOL obj))
  251.                      ((RATNUM) (dump-RATNUM obj))
  252.                      ((CPXNUM) (dump-CPXNUM obj))
  253.                      ((STRING) (dump-STRING obj))
  254.                      ((FLONUM) (dump-FLONUM obj))
  255.                      ((BIGNUM) (dump-BIGNUM obj))
  256.                      (else
  257.                       (compiler-internal-error
  258.                         "dump-object, can't dump object 'obj':" obj))))
  259.     ((PROCEDURE)   (dump-PROCEDURE obj))
  260.     (else
  261.      (compiler-internal-error
  262.        "dump-object, can't dump object 'obj':" obj))))
  263.  
  264. ;------------------------------------------------------------------------------
  265.  
  266. (define (dump-PAIR pair)
  267.   (ofile-long pair-prefix)
  268.   (ofile-ref (cdr pair))
  269.   (ofile-ref (car pair)))
  270.  
  271. ;------------------------------------------------------------------------------
  272.  
  273. (define (dump-VECTOR v)
  274.   (ofile-long (+ (* (vector-length v) #x400) (* subtype-VECTOR 8)))
  275.   (let ((len (vector-length v)))
  276.     (let loop ((i 0))
  277.       (if (< i len)
  278.         (begin
  279.           (ofile-ref (vector-ref v i))
  280.           (loop (+ i 1)))))))
  281.  
  282. ;------------------------------------------------------------------------------
  283.  
  284. (define (dump-SYMBOL sym)
  285.   (compiler-internal-error
  286.     "dump-symbol, can't dump SYMBOL type"))
  287.  
  288. ;------------------------------------------------------------------------------
  289.  
  290. (define (dump-RATNUM x)
  291.   (ofile-long (+ (* 2 #x400) (* subtype-RATNUM 8)))
  292.   (ofile-ref (numerator x))
  293.   (ofile-ref (denominator x)))
  294.  
  295. ;------------------------------------------------------------------------------
  296.  
  297. (define (dump-CPXNUM x)
  298.   (ofile-long (+ (* 2 #x400) (* subtype-CPXNUM 8)))
  299.   (ofile-ref (real-part x))
  300.   (ofile-ref (imag-part x)))
  301.  
  302. ;------------------------------------------------------------------------------
  303.  
  304. (define (dump-STRING s)
  305.   (ofile-long (+ (* (string-length s) #x100) (* subtype-STRING 8)))
  306.   (let ((len (string-length s)))
  307.     (define (ref i) (if (>= i len) 0 (character-encoding (string-ref s i))))
  308.     (let loop ((i 0))
  309.       (if (< i len)
  310.         (begin
  311.           (ofile-word (+ (* (ref i) 256) (ref (+ i 1))))
  312.           (loop (+ i 2)))))))
  313.  
  314. ;------------------------------------------------------------------------------
  315.  
  316. (define (dump-FLONUM x)
  317.   (let ((bits (flonum->bits x)))
  318.     (ofile-long (+ (* 2 #x400) (* subtype-FLONUM 8)))
  319.     (ofile-long (quotient bits #x100000000))
  320.     (ofile-long (modulo   bits #x100000000))))
  321.  
  322. (define (flonum->inexact-exponential-format x)
  323.  
  324.   (define (exp-form-pos x y i)
  325.     (let ((i*2 (+ i i)))
  326.       (let ((z (if (and (not (< flonum-e-bias i*2))
  327.                         (not (< x y)))
  328.                  (exp-form-pos x (* y y) i*2)
  329.                  (cons x 0))))
  330.         (let ((a (car z)) (b (cdr z)))
  331.           (let ((i+b (+ i b)))
  332.             (if (and (not (< flonum-e-bias i+b))
  333.                      (not (< a y)))
  334.               (begin
  335.                 (set-car! z (/ a y))
  336.                 (set-cdr! z i+b)))
  337.             z)))))
  338.  
  339.   (define (exp-form-neg x y i)
  340.     (let ((i*2 (+ i i)))
  341.       (let ((z (if (and (< i*2 flonum-e-bias-minus-1)
  342.                         (< x y))
  343.                  (exp-form-neg x (* y y) i*2)
  344.                  (cons x 0))))
  345.         (let ((a (car z)) (b (cdr z)))
  346.           (let ((i+b (+ i b)))
  347.             (if (and (< i+b flonum-e-bias-minus-1)
  348.                      (< a y))
  349.               (begin
  350.                 (set-car! z (/ a y))
  351.                 (set-cdr! z i+b)))
  352.             z)))))
  353.  
  354.   (define (exp-form x)
  355.     (if (< x inexact-+1)
  356.       (let ((z (exp-form-neg x inexact-+1/2 1)))
  357.         (set-car! z (* inexact-+2 (car z)))
  358.         (set-cdr! z (- -1 (cdr z)))
  359.         z)
  360.       (exp-form-pos x inexact-+2 1)))
  361.  
  362.   (if (negative? x)
  363.     (let ((z (exp-form (- inexact-0 x))))
  364.       (set-car! z (- inexact-0 (car z)))
  365.       z)
  366.     (exp-form x)))
  367.  
  368. (define (flonum->exact-exponential-format x)
  369.   (let ((z (flonum->inexact-exponential-format x)))
  370.     (let ((y (car z)))
  371.       (cond ((not (< y inexact-+2))
  372.              (set-car! z flonum-+m-min)
  373.              (set-cdr! z flonum-e-bias-plus-1))
  374.             ((not (< inexact--2 y))
  375.              (set-car! z flonum--m-min)
  376.              (set-cdr! z flonum-e-bias-plus-1))
  377.             (else
  378.              (set-car! z
  379.                (truncate (inexact->exact (* (car z) inexact-m-min))))))
  380.       (set-cdr! z (- (cdr z) flonum-m-bits))
  381.       z)))
  382.  
  383. (define (flonum->bits x)
  384.  
  385.   (define (bits a b)
  386.     (if (< a flonum-+m-min)
  387.       a
  388.       (+ (- a flonum-+m-min)
  389.          (* (+ (+ b flonum-m-bits) flonum-e-bias)
  390.             flonum-+m-min))))
  391.  
  392.   (let ((z (flonum->exact-exponential-format x)))
  393.     (let ((a (car z)) (b (cdr z)))
  394.       (if (negative? a)
  395.         (+ flonum-sign-bit (bits (- 0 a) b))
  396.         (bits a b)))))
  397.  
  398. (define flonum-m-bits         52)
  399. (define flonum-e-bits         11)
  400. (define flonum-sign-bit       #x8000000000000000) ; (expt 2 (+ flonum-e-bits flonum-m-bits))
  401. (define flonum-+m-min         4503599627370496)   ; (expt 2 flonum-m-bits)
  402. (define flonum--m-min         -4503599627370496)  ; (- flonum-+m-min)
  403. (define flonum-e-bias         1023) ; (- (expt 2 (- flonum-e-bits 1)) 1)
  404. (define flonum-e-bias-plus-1  1024) ; (+ flonum-e-bias 1)
  405. (define flonum-e-bias-minus-1 1022) ; (- flonum-e-bias 1)
  406.  
  407. (define inexact-m-min         (exact->inexact flonum-+m-min))
  408. (define inexact-+2            (exact->inexact 2))
  409. (define inexact--2            (exact->inexact -2))
  410. (define inexact-+1            (exact->inexact 1))
  411. (define inexact-+1/2          (exact->inexact (/ 1 2)))
  412. (define inexact-0             (exact->inexact 0))
  413.  
  414. ;------------------------------------------------------------------------------
  415.  
  416. (define (dump-BIGNUM x)
  417.  
  418.   (define radix 16384)
  419.  
  420.   (define (integer->digits n)
  421.     (if (= n 0)
  422.       '()
  423.       (cons (remainder n radix)
  424.             (integer->digits (quotient n radix)))))
  425.  
  426.   (let ((l (integer->digits (abs x))))
  427.  
  428.     (ofile-long (+ (* (+ (length l) 1) #x200) (* subtype-BIGNUM 8)))
  429.  
  430.     (if (< x 0)
  431.       (ofile-word 0)
  432.       (ofile-word 1))
  433.  
  434.     (for-each ofile-word l)))
  435.  
  436. ;------------------------------------------------------------------------------
  437.  
  438. (define (dump-PROCEDURE proc)
  439.   (let ((bbs (proc-obj-code proc)))
  440.  
  441.     (set! entry-lbl-num (bbs-entry-lbl-num bbs))
  442.     (set! label-counter (bbs-lbl-counter bbs))
  443.     (set! var-descr-queue (queue-empty))
  444.     (set! first-class-label-queue (queue-empty))
  445.     (set! deferred-code-queue (queue-empty))
  446.  
  447.     (if *info-port*
  448.       (begin
  449.         (display "  #[" *info-port*)
  450.         (if (proc-obj-primitive? proc)
  451.           (display "primitive " *info-port*)
  452.           (display "procedure " *info-port*))
  453.         (display (proc-obj-name proc) *info-port*)
  454.         (display "]" *info-port*)))
  455.  
  456.     (if (proc-obj-primitive? proc)
  457.       (ofile-prim-proc (proc-obj-name proc))
  458.       (ofile-user-proc))
  459.  
  460.     (asm.begin!)
  461.  
  462.     (let loop ((prev-bb #f)
  463.                (prev-pvm-instr #f)
  464.                (l (bbs->code-list bbs)))
  465.       (if (not (null? l))
  466.         (let ((pres-bb (code-bb (car l)))
  467.               (pres-pvm-instr (code-pvm-instr (car l)))
  468.               (pres-slots-needed (code-slots-needed (car l)))
  469.               (next-pvm-instr (if (null? (cdr l))
  470.                                 #f
  471.                                 (code-pvm-instr (cadr l)))))
  472.  
  473.           (if ofile-asm? (asm-comment (car l)))
  474.  
  475.           (gen-pvm-instr prev-pvm-instr
  476.                          pres-pvm-instr
  477.                          next-pvm-instr
  478.                          pres-slots-needed)
  479.  
  480.           (loop pres-bb pres-pvm-instr (cdr l)))))
  481.  
  482.     (asm.end!
  483.       (if debug-info?
  484.         (vector (lst->vector (queue->list first-class-label-queue))
  485.                 (lst->vector (queue->list var-descr-queue)))
  486.         #f))
  487.  
  488.     (if *info-port*
  489.       (newline *info-port*))
  490.  
  491.     (set! var-descr-queue '())
  492.     (set! first-class-label-queue '())
  493.     (set! deferred-code-queue '())
  494.     (set! instr-source '())
  495.     (set! entry-frame '())
  496.     (set! exit-frame '())))
  497.  
  498. (define label-counter '())
  499. (define entry-lbl-num '())
  500. (define var-descr-queue '())
  501. (define first-class-label-queue '())
  502. (define deferred-code-queue '())
  503. (define instr-source '())
  504. (define entry-frame '())
  505. (define exit-frame '())
  506.  
  507. (define (defer-code! thunk)
  508.   (queue-put! deferred-code-queue thunk))
  509.  
  510. (define (gen-deferred-code!)
  511.   (let loop ()
  512.     (if (not (queue-empty? deferred-code-queue))
  513.       (let ((thunk (queue-get! deferred-code-queue)))
  514.         (thunk)
  515.         (loop)))))
  516.  
  517. (define (add-var-descr! descr)
  518.  
  519.   (define (index x l)
  520.     (let loop ((l l) (i 0))
  521.       (cond ((not (pair? l))    #f)
  522.             ((equal? (car l) x) i)
  523.             (else               (loop (cdr l) (+ i 1))))))
  524.  
  525.   (let ((n (index descr (queue->list var-descr-queue))))
  526.     (if n
  527.       n
  528.       (let ((m (length (queue->list var-descr-queue))))
  529.         (queue-put! var-descr-queue descr)
  530.         m))))
  531.  
  532. (define (add-first-class-label! source slots frame)
  533.   (let loop ((i 0) (l1 slots) (l2 '()))
  534.     (if (pair? l1)
  535.       (let ((var (car l1)))
  536.         (let ((x (frame-live? var frame)))
  537.           (if (and x (or (pair? x) (not (temp-var? x))))
  538.             (let ((descr-index
  539.                     (add-var-descr!
  540.                      (if (pair? x)
  541.                         (map (lambda (y) (add-var-descr! (var-name y))) x)
  542.                         (var-name x)))))
  543.               (loop (+ i 1) (cdr l1) (cons (+ (* i 16384) descr-index) l2)))
  544.             (loop (+ i 1) (cdr l1) l2))))
  545.       (let ((label-descr (lst->vector (cons 0 (cons source l2)))))
  546.         (queue-put! first-class-label-queue label-descr)
  547.         label-descr))))
  548.  
  549. (define (gen-pvm-instr prev-pvm-instr pvm-instr next-pvm-instr sn)
  550.  
  551.   (set! instr-source (comment-get (pvm-instr-comment pvm-instr) 'SOURCE))
  552.   (set! exit-frame   (pvm-instr-frame pvm-instr))
  553.   (set! entry-frame  (and prev-pvm-instr (pvm-instr-frame prev-pvm-instr)))
  554.  
  555.   (case (pvm-instr-type pvm-instr)
  556.  
  557.     ((LABEL)
  558.      (set! entry-frame exit-frame)
  559.      (set! current-fs (frame-size exit-frame))
  560.      (case (LABEL-type pvm-instr)
  561.        ((SIMP)
  562.         (gen-LABEL-SIMP (LABEL-lbl-num pvm-instr)
  563.                         sn))
  564.        ((TASK)
  565.         (gen-LABEL-TASK (LABEL-lbl-num pvm-instr)
  566.                         (LABEL-TASK-method pvm-instr)
  567.                         sn))
  568.        ((PROC)
  569.         (gen-LABEL-PROC (LABEL-lbl-num pvm-instr)
  570.                         (LABEL-PROC-nb-parms pvm-instr)
  571.                         (LABEL-PROC-min pvm-instr)
  572.                         (LABEL-PROC-rest? pvm-instr)
  573.                         (LABEL-PROC-closed? pvm-instr)
  574.                         sn))
  575.        ((RETURN)
  576.         (gen-LABEL-RETURN (LABEL-lbl-num pvm-instr)
  577.                           (LABEL-RETURN-task-method pvm-instr)
  578.                           sn))
  579.        (else
  580.         (compiler-internal-error
  581.           "gen-pvm-instr, unknown label type"))))
  582.  
  583.     ((APPLY)
  584.      (gen-APPLY (APPLY-prim pvm-instr)
  585.                 (APPLY-opnds pvm-instr)
  586.                 (APPLY-loc pvm-instr)
  587.                 sn))
  588.  
  589.     ((COPY)
  590.      (gen-COPY (COPY-opnd pvm-instr)
  591.                (COPY-loc pvm-instr)
  592.                sn))
  593.  
  594.     ((MAKE_CLOSURES)
  595.      (gen-MAKE_CLOSURES (MAKE_CLOSURES-parms pvm-instr)
  596.                         sn))
  597.  
  598.     ((COND)
  599.      (gen-COND (COND-test pvm-instr)
  600.                (COND-opnds pvm-instr)
  601.                (COND-true pvm-instr)
  602.                (COND-false pvm-instr)
  603.                (COND-intr-check? pvm-instr)
  604.                (if (and next-pvm-instr
  605.                         (memq (LABEL-type next-pvm-instr) '(SIMP TASK)))
  606.                  (LABEL-lbl-num next-pvm-instr)
  607.                  #f)))
  608.  
  609.     ((JUMP)
  610.      (gen-JUMP (JUMP-opnd pvm-instr)
  611.                (JUMP-nb-args pvm-instr)
  612.                (JUMP-intr-check? pvm-instr)
  613.                (if (and next-pvm-instr
  614.                         (memq (LABEL-type next-pvm-instr) '(SIMP TASK)))
  615.                  (LABEL-lbl-num next-pvm-instr)
  616.                  #f)))
  617.  
  618.     (else
  619.      (compiler-internal-error
  620.        "gen-pvm-instr, unknown 'pvm-instr':"
  621.        pvm-instr))))
  622.  
  623.  
  624. ;------------------------------------------------------------------------------
  625. ;
  626. ; Useful tools:
  627.  
  628. (define (reg-in-opnd68 opnd) ; return the register used in an operand
  629.   (cond ((dreg? opnd) opnd)
  630.         ((areg? opnd) opnd)
  631.         ((ind? opnd)  (ind-areg opnd))
  632.         ((pinc? opnd) (pinc-areg opnd))
  633.         ((pdec? opnd) (pdec-areg opnd))
  634.         ((disp? opnd) (disp-areg opnd))
  635.         ((inx? opnd)  (inx-ireg opnd)) ; disregard address register
  636.         (else         #f)))
  637.  
  638. (define (temp-in-opnd68 opnd) ; return the temporary reg used in an operand
  639.   (let ((reg (reg-in-opnd68 opnd)))
  640.     (if reg
  641.       (cond ((identical-opnd68? reg dtemp1) reg)
  642.             ((identical-opnd68? reg atemp1) reg)
  643.             ((identical-opnd68? reg atemp2) reg)
  644.             (else                           #f))
  645.       #f)))
  646.  
  647. (define (pick-atemp keep) ; return a temp address reg different from 'keep'
  648.   (if (and keep (identical-opnd68? keep atemp1))
  649.     atemp2
  650.     atemp1))
  651.  
  652. (define return-reg '())
  653.  
  654. ; structures:
  655.  
  656. (define max-nb-args           1024)
  657.  
  658. (define heap-allocation-fudge (* pointer-size (+ (* 2 max-nb-args) 1024)))
  659.  
  660. (define intr-flag             0)
  661. (define ltq-tail              1)
  662. (define ltq-head              2)
  663. (define heap-lim              12)
  664. (define closure-lim           17)
  665. (define closure-ptr           18)
  666. (define workq-head            22)
  667.  
  668. (define intr-flag-slot   (make-disp* pstate-reg (* pointer-size intr-flag)))
  669. (define ltq-tail-slot    (make-disp* pstate-reg (* pointer-size ltq-tail)))
  670. (define ltq-head-slot    (make-disp* pstate-reg (* pointer-size ltq-head)))
  671. (define heap-lim-slot    (make-disp* pstate-reg (* pointer-size heap-lim)))
  672. (define closure-lim-slot (make-disp* pstate-reg (* pointer-size closure-lim)))
  673. (define closure-ptr-slot (make-disp* pstate-reg (* pointer-size closure-ptr)))
  674. (define workq-head-slot  (make-disp* pstate-reg (* pointer-size workq-head)))
  675.  
  676. (define TOUCH-trap                1)
  677. (define non-proc-jump-trap        6)
  678. (define rest-params-trap          7)
  679. (define rest-params-closed-trap   8)
  680. (define wrong-nb-arg1-trap        9)
  681. (define wrong-nb-arg1-closed-trap 10)
  682. (define wrong-nb-arg2-trap        11)
  683. (define wrong-nb-arg2-closed-trap 12)
  684. (define heap-alloc1-trap          13)
  685. (define heap-alloc2-trap          14)
  686. (define closure-alloc-trap        15)
  687. (define delay-future-trap         16)
  688. (define eager-future-trap         17)
  689. (define steal-conflict-trap       18)
  690. (define intr-trap                 24)
  691.  
  692. (define cache-line-length         16) ; works on 68020/68030/68040
  693.  
  694. (define intr-latency '())
  695. (set! intr-latency                10) ; controls interrupt latency
  696.  
  697. (define lazy-task-kind '())
  698. (set! lazy-task-kind              'MESSAGE-PASSING-LTQ) ; what kind of LTC
  699.  
  700. ;------------------------------------------------------------------------------
  701.  
  702. (define (stat-clear!)
  703.   (set! *stats* (cons 0 '())))
  704.  
  705. (define (stat-dump!)
  706.   (emit-stat (cdr *stats*)))
  707.  
  708. (define (stat-add! bin count)
  709.  
  710.   (define (add! stats bin count)
  711.     (set-car! stats (+ (car stats) count))
  712.     (if (not (null? bin))
  713.       (let ((x (assoc (car bin) (cdr stats))))
  714.         (if x
  715.           (add! (cdr x) (cdr bin) count)
  716.           (begin
  717.             (set-cdr! stats (cons (list (car bin) 0) (cdr stats)))
  718.             (add! (cdadr stats) (cdr bin) count))))))
  719.  
  720.   (add! *stats* bin count))
  721.  
  722. (define (fetch-stat-add! pvm-opnd)
  723.   (opnd-stat-add! 'fetch pvm-opnd))
  724.  
  725. (define (store-stat-add! pvm-opnd)
  726.   (opnd-stat-add! 'store pvm-opnd))
  727.  
  728. (define (jump-stat-add! pvm-opnd)
  729.   (opnd-stat-add! 'jump pvm-opnd))
  730.  
  731. (define (opnd-stat-add! type opnd)
  732.   (cond ((reg? opnd)
  733.          (stat-add! (list 'pvm-opnd 'reg type (reg-num opnd)) 1))
  734.         ((stk? opnd)
  735.          (stat-add! (list 'pvm-opnd 'stk type) 1))
  736.         ((glo? opnd)
  737.          (stat-add! (list 'pvm-opnd 'glo type (glo-name opnd)) 1))
  738.         ((clo? opnd)
  739.          (stat-add! (list 'pvm-opnd 'clo type) 1)
  740.          (fetch-stat-add! (clo-base opnd)))
  741.         ((lbl? opnd)
  742.          (stat-add! (list 'pvm-opnd 'lbl type) 1))
  743.         ((obj? opnd)
  744.          (let ((val (obj-val opnd)))
  745.            (if (number? val)
  746.              (stat-add! (list 'pvm-opnd 'obj type val) 1)
  747.              (stat-add! (list 'pvm-opnd 'obj type (obj-type val)) 1))))
  748.         (else
  749.          (compiler-internal-error
  750.            "opnd-stat-add!, unknown 'opnd':" opnd))))
  751.  
  752. (define (opnd-stat opnd)
  753.   (cond ((reg? opnd) 'reg)
  754.         ((stk? opnd) 'stk)
  755.         ((glo? opnd) 'glo)
  756.         ((clo? opnd) 'clo)
  757.         ((lbl? opnd) 'lbl)
  758.         ((obj? opnd) 'obj)
  759.         (else
  760.          (compiler-internal-error
  761.            "opnd-stat, unknown 'opnd':" opnd))))
  762.  
  763. (define *stats* '())
  764.  
  765. ;------------------------------------------------------------------------------
  766.  
  767. (define (move-opnd68-to-loc68 opnd loc)
  768.   (if (not (identical-opnd68? opnd loc))
  769.     (if (imm? opnd)
  770.       (move-n-to-loc68 (imm-val opnd) loc)
  771.       (emit-move.l opnd loc))))
  772.  
  773. (define (move-obj-to-loc68 obj loc)
  774.   (let ((n (obj-encoding obj)))
  775.     (if n
  776.       (move-n-to-loc68 n loc)
  777.       (emit-move.l (emit-const obj) loc))))
  778.  
  779. (define (move-n-to-loc68 n loc)
  780.   (cond ((= n bits-NULL)
  781.          (emit-move.l null-reg loc))
  782.         ((= n bits-FALSE)
  783.          (emit-move.l false-reg loc))
  784.         ((and (dreg? loc) (>= n -128) (<= n 127))
  785.          (emit-moveq n loc))
  786.         ((and (areg? loc) (>= n -32768) (<= n 32767))
  787.          (emit-move.w (make-imm n) loc))
  788.         ((and (areg? loc) (>= n 0) (<= n 65535))
  789.          (emit-lea* n loc))
  790.         ((and (identical-opnd68? loc pdec-sp) (>= n 0) (<= n 65535))
  791.          (emit-pea* n))
  792.         ((= n 0)
  793.          (emit-clr.l loc))
  794.         ((and (not (and (inx? loc) (= (inx-ireg loc) dtemp1))) (>= n -128) (<= n 127))
  795.          (emit-moveq n dtemp1)
  796.          (emit-move.l dtemp1 loc))
  797.         (else
  798.          (emit-move.l (make-imm n) loc))))
  799.  
  800. (define (add-n-to-loc68 n loc)
  801.   (if (not (= n 0))
  802.     (cond ((and (>= n -8) (<= n 8))
  803.            (if (> n 0) (emit-addq.l n loc) (emit-subq.l (- n) loc)))
  804.           ((and (areg? loc) (>= n -32768) (<= n 32767))
  805.            (emit-lea (make-disp loc n) loc))
  806.           ((and (not (identical-opnd68? loc dtemp1)) (>= n -128) (<= n 128))
  807.            (emit-moveq (- (abs n)) dtemp1)
  808.            (if (> n 0) (emit-sub.l dtemp1 loc) (emit-add.l dtemp1 loc)))
  809.           (else
  810.            (emit-add.l (make-imm n) loc)))))
  811.  
  812. (define (power-of-2 n)
  813.   (let loop ((i 0) (k 1))
  814.     (cond ((= k n) i)
  815.           ((> k n) #f)
  816.           (else    (loop (+ i 1) (* k 2))))))
  817.  
  818. (define (mul-n-to-reg68 n reg)
  819.   (if (= n 0)
  820.     (emit-moveq 0 reg)
  821.     (let ((abs-n (abs n)))
  822.       (if (= abs-n 1)
  823.         (if (< n 0) (emit-neg.l reg))
  824.         (let ((shift (power-of-2 abs-n)))
  825.           (if shift
  826.             (let ((m (min shift 32)))
  827.               (if (or (<= m 8) (identical-opnd68? reg dtemp1))
  828.                 (let loop ((i m))
  829.                   (if (> i 0)
  830.                     (begin (emit-asl.l (make-imm (min i 8)) reg) (loop (- i 8)))))
  831.                 (begin
  832.                   (emit-moveq m dtemp1)
  833.                   (emit-asl.l dtemp1 reg)))
  834.               (if (< n 0) (emit-neg.l reg)))
  835.             (emit-muls.l (make-imm n) reg)))))))
  836.  
  837. (define (div-n-to-reg68 n reg)
  838.   (let ((abs-n (abs n)))
  839.     (if (= abs-n 1)
  840.       (if (< n 0) (emit-neg.l reg))
  841.       (let ((shift (power-of-2 abs-n)))
  842.         (if shift
  843.           (let ((m (min shift 32))
  844.                 (lbl (new-lbl!)))
  845.             (emit-move.l reg reg)
  846.             (emit-bpl lbl)
  847.             (add-n-to-loc68 (* (- abs-n 1) 8) reg)
  848.             (emit-label lbl)
  849.             (if (or (<= m 8) (identical-opnd68? reg dtemp1))
  850.               (let loop ((i m))
  851.                 (if (> i 0)
  852.                   (begin (emit-asr.l (make-imm (min i 8)) reg) (loop (- i 8)))))
  853.               (begin
  854.                 (emit-moveq m dtemp1)
  855.                 (emit-asr.l dtemp1 reg)))
  856.             (if (< n 0) (emit-neg.l reg)))
  857.           (emit-divsl.l (make-imm n) reg reg))))))
  858.  
  859. (define (cmp-n-to-opnd68 n opnd)
  860.   (cond ((= n bits-NULL)
  861.          (emit-cmp.l opnd null-reg)
  862.          #f)
  863.         ((= n bits-FALSE)
  864.          (emit-cmp.l opnd false-reg)
  865.          #f)
  866.         ((or (pcr? opnd) (imm? opnd))
  867.          (if (= n 0)
  868.            (begin
  869.              (emit-move.l opnd dtemp1)
  870.              #t)
  871.            (begin
  872.              (move-opnd68-to-loc68 opnd atemp1)
  873.              (if (and (>= n -32768) (<= n 32767))
  874.                (emit-cmp.w (make-imm n) atemp1)
  875.                (emit-cmp.l (make-imm n) atemp1))
  876.              #t)))
  877.         ((= n 0)
  878.          (emit-move.l opnd dtemp1)
  879.          #t)
  880.         ((and (>= n -128) (<= n 127) (not (identical-opnd68? opnd dtemp1)))
  881.          (emit-moveq n dtemp1)
  882.          (emit-cmp.l opnd dtemp1)
  883.          #f)
  884.         (else
  885.          (emit-cmp.l (make-imm n) opnd)
  886.          #t)))
  887.  
  888. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  889.  
  890. (define (might-touch-opnd? opnd)
  891.   (cond ((pot-fut? opnd)
  892.          #t)
  893.         ((clo? opnd)
  894.          (might-touch-opnd? (clo-base opnd)))
  895.         (else
  896.          #f)))
  897.  
  898. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  899.  
  900. ; current-fs is the current frame size.
  901.  
  902. (define current-fs '())
  903.  
  904. ; (adjust-current-fs n) adds 'n' to the current frame size.
  905.  
  906. (define (adjust-current-fs n)
  907.   (set! current-fs (+ current-fs n)))
  908.  
  909. ; (new-lbl!) returns a new label number different from all others in this
  910. ; procedure.
  911.  
  912. (define (new-lbl!)
  913.   (label-counter))
  914.  
  915. ; (needed? loc sn) is false if we are sure that the location 'loc' is not
  916. ; needed (assuming that only 'sn' slots on the stack are needed).
  917.  
  918. (define (needed? loc sn)
  919.   (and loc (if (stk? loc) (<= (stk-num loc) sn) #t)))
  920.  
  921. ; (sn-opnd opnd sn) returns the number of slots that are needed in the
  922. ; stack frame to reference 'opnd'.  'sn' is the number of slots that must be
  923. ; preserved in the frame.
  924.  
  925. (define (sn-opnd opnd sn)
  926.   (cond ((stk? opnd)
  927.          (max (stk-num opnd) sn))
  928.         ((clo? opnd)
  929.          (sn-opnd (clo-base opnd) sn))
  930.         (else
  931.          sn)))
  932.  
  933. ; (sn-opnds opnds sn) returns the number of slots that are needed in the
  934. ; stack frame to reference all of the operands in 'opnds'.  'sn' is the number
  935. ; of slots that must be preserved in the frame.
  936.  
  937. (define (sn-opnds opnds sn)
  938.   (if (null? opnds)
  939.     sn
  940.     (sn-opnd (car opnds) (sn-opnds (cdr opnds) sn))))
  941.  
  942. ; (sn-opnd68 opnd sn) is similar to 'sn-opnd' except that it works with
  943. ; M68000 operands.
  944.  
  945. (define (sn-opnd68 opnd sn)
  946.   (cond ((and (disp*? opnd) (identical-opnd68? (disp*-areg opnd) sp-reg))
  947.          (max (disp*-offset opnd) sn))
  948.         ((identical-opnd68? opnd pdec-sp)
  949.          (max (+ current-fs 1) sn))
  950.         ((identical-opnd68? opnd pinc-sp)
  951.          (max current-fs sn))
  952.         (else
  953.          sn)))
  954.  
  955. ; (resize-frame n) generates the code to move the stack pointer to
  956. ; frame slot number 'n'.
  957.  
  958. (define (resize-frame n)
  959.   (let ((x (- n current-fs)))
  960.     (adjust-current-fs x)
  961.     (add-n-to-loc68 (* (- pointer-size) x) sp-reg)))
  962.  
  963. ; (shrink-frame n) generates the code to resize the frame to leave
  964. ; only the first 'n' slots on the stack.
  965.  
  966. (define (shrink-frame n)
  967.   (cond ((< n current-fs)
  968.          (resize-frame n))
  969.         ((> n current-fs)
  970.          (compiler-internal-error "shrink-frame, can't increase frame size"))))
  971.  
  972. ; (make-top-of-frame n sn) generates the code to resize the frame so that
  973. ; slot 'n' is on top of the stack while leaving at least 'sn' slots
  974. ; in the frame.
  975.  
  976. (define (make-top-of-frame n sn)
  977.   (if (and (< n current-fs) (>= n sn)) (resize-frame n)))
  978.  
  979. ; (make-top-of-frame-if-stk-opnd68 opnd sn) generates the code to resize the
  980. ; frame so that a subsequent reference to 'opnd' (if it is a stack slot) will
  981. ; be easier.  'sn' is the number of slots that must be preserved in the
  982. ; frame (the stack frame might be shrunk down to that size).
  983.  
  984. (define (make-top-of-frame-if-stk-opnd68 opnd sn)
  985.   (if (frame-base-rel? opnd)
  986.     (make-top-of-frame (frame-base-rel-slot opnd) sn)))
  987.  
  988. ; (make-top-of-frame-if-stk-opnds68 opnd1 opnd2 sn) generates the code to resize
  989. ; the frame so that subsequent references to 'opnd1' and 'opnd2' (if they are
  990. ; stack slots) will be easier.  'sn' is the number of slots that must be
  991. ; preserved in the frame (the stack frame might be shrunk down to that size).
  992.  
  993. (define (make-top-of-frame-if-stk-opnds68 opnd1 opnd2 sn)
  994.   (if (frame-base-rel? opnd1)
  995.     (let ((slot1 (frame-base-rel-slot opnd1)))
  996.       (if (frame-base-rel? opnd2)
  997.         (make-top-of-frame (max (frame-base-rel-slot opnd2) slot1) sn)
  998.         (make-top-of-frame slot1 sn)))
  999.     (if (frame-base-rel? opnd2)
  1000.       (make-top-of-frame (frame-base-rel-slot opnd2) sn))))
  1001.  
  1002. ; (opnd68->true-opnd68 opnd sn) transforms 'frame base relative' stack operands
  1003. ; into 'top of stack relative' stack operands (as they must appear to the
  1004. ; processor).  'push' or 'pop' operands are returned when possible.  All
  1005. ; other operands are already correct so they are simply returned unchanged.
  1006.  
  1007. (define (opnd68->true-opnd68 opnd sn)
  1008.   (if (frame-base-rel? opnd)
  1009.     (let ((slot (frame-base-rel-slot opnd)))
  1010.  
  1011.       (cond ((> slot current-fs) ; push?
  1012.              (adjust-current-fs 1)
  1013.              pdec-sp)             
  1014.  
  1015.             ((and (= slot current-fs) (< sn current-fs)) ; pop?
  1016.              (adjust-current-fs -1)
  1017.              pinc-sp)
  1018.  
  1019.             (else
  1020.              (make-disp* sp-reg (* pointer-size (- current-fs slot))))))
  1021.  
  1022.     opnd))
  1023.  
  1024. ; (move-opnd68-to-any-areg opnd keep sn) generates the code to move the value
  1025. ; from a M68000 operand to any address register.  'keep' (if not #f) is a
  1026. ; M68000 register that must not be modified.
  1027.  
  1028. (define (move-opnd68-to-any-areg opnd keep sn)
  1029.   (if (areg? opnd)
  1030.     opnd
  1031.     (let ((areg (pick-atemp keep)))
  1032.       (make-top-of-frame-if-stk-opnd68 opnd sn)
  1033.       (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd sn) areg)
  1034.       areg)))
  1035.  
  1036. ; (clo->opnd68 opnd keep sn) returns the M68000 operand corresponding
  1037. ; to the PVM closed operand 'opnd'.  'keep' (if not #f) is a M68000
  1038. ; register that must not be modified.  Code might be generated in the
  1039. ; process (to load the base in an address register and/or to touch
  1040. ; the base if it is a touch operand).
  1041.  
  1042. (define (clo->opnd68 opnd keep sn)
  1043.   (let ((base (clo-base opnd))
  1044.         (offs (closed-var-offset (clo-index opnd))))
  1045.     (if (lbl? base)
  1046.       (make-pcr (lbl-num base) offs)
  1047.       (clo->loc68 opnd keep sn))))
  1048.  
  1049. ; (clo->loc68 opnd keep sn) is similar in function to 'clo->opnd68' except
  1050. ; that a 'data alterable' addressing mode operand is returned.
  1051.  
  1052. (define (clo->loc68 opnd keep sn)
  1053.   (let ((base (clo-base opnd))
  1054.         (offs (closed-var-offset (clo-index opnd))))
  1055.  
  1056.     (cond ((eq? base return-reg)
  1057.            (make-disp* (reg->reg68 base) offs))
  1058.  
  1059.           ((obj? base)
  1060.            (let ((areg (pick-atemp keep)))
  1061.              (move-obj-to-loc68 (obj-val base) areg)
  1062.              (make-disp* areg offs)))
  1063.  
  1064.           ((pot-fut? base)
  1065.            (let ((reg (touch-opnd-to-any-reg68 base keep sn)))
  1066.              (make-disp* (move-opnd68-to-any-areg reg keep sn) offs)))
  1067.  
  1068.           (else
  1069.            (let ((areg (pick-atemp keep)))
  1070.              (move-opnd-to-loc68 base areg sn)
  1071.              (make-disp* areg offs))))))
  1072.  
  1073. ; (reg->reg68 reg) returns the M68000 register corresponding to the PVM
  1074. ; register 'reg'.
  1075.  
  1076. (define (reg->reg68 reg)
  1077.   (reg-num->reg68 (reg-num reg)))
  1078.  
  1079. (define (reg-num->reg68 num)
  1080.   (if (= num 0) (make-areg pvm-reg0) (make-dreg (+ (- num 1) pvm-reg1))))
  1081.  
  1082. ; (opnd->opnd68 opnd keep sn) returns the M68000 operand corresponding
  1083. ; to the PVM operand 'opnd'.  'keep' (if not #f) is a M68000
  1084. ; register that must not be modified.  Code might be generated in the
  1085. ; process (to load the base in an address register and/or to touch
  1086. ; the base if it is a touch operand).
  1087.  
  1088. (define (opnd->opnd68 opnd keep sn)
  1089.   (cond ((lbl? opnd)
  1090.          (let ((areg (pick-atemp keep)))
  1091.            (emit-lea (make-pcr (lbl-num opnd) 0) areg)
  1092.            areg))
  1093.  
  1094.         ((obj? opnd)
  1095.          (let ((val (obj-val opnd)))
  1096.            (if (proc-obj? val)
  1097.              (let ((num (add-object val))
  1098.                    (areg (pick-atemp keep)))
  1099.                (if num
  1100.                  (emit-move-proc num areg)
  1101.                  (emit-move-prim val areg))
  1102.                areg)
  1103.              (let ((n (obj-encoding val)))
  1104.                (if n
  1105.                  (make-imm n)
  1106.                  (emit-const val))))))
  1107.  
  1108.         ((clo? opnd)
  1109.          (clo->opnd68 opnd keep sn))
  1110.  
  1111.         (else
  1112.          (loc->loc68 opnd keep sn))))
  1113.  
  1114. ; (loc->loc68 loc keep sn) returns the M68000 'data alterable' addressing
  1115. ; mode operand corresponding to the PVM location 'loc'.  'keep' (if not #f)
  1116. ; is a M68000 register that must not be modified.  Code might be generated
  1117. ; in the process (to load the base in an address register and/or to touch
  1118. ; the base if it is a touch operand).
  1119.  
  1120. (define (loc->loc68 loc keep sn)
  1121.  
  1122.   (cond ((reg? loc)
  1123.          (reg->reg68 loc))
  1124.  
  1125.         ((stk? loc)
  1126.          (make-frame-base-rel (stk-num loc)))
  1127.          ; will be converted later by 'opnd68->true-opnd68'
  1128.  
  1129.         ((glo? loc)
  1130.          (make-glob (glo-name loc)))
  1131.  
  1132.         ((clo? loc)
  1133.          (clo->loc68 loc keep sn))
  1134.  
  1135.         (else
  1136.          (compiler-internal-error
  1137.            "loc->loc68, unknown 'loc':" loc))))
  1138.  
  1139. ; (move-opnd68-to-loc opnd loc sn) generates the code to move a
  1140. ; M68000 operand into a PVM location.  'sn' is the number of slots that
  1141. ; must be preserved in the frame (the stack frame might be shrunk down
  1142. ; to that size).
  1143.  
  1144. (define (move-opnd68-to-loc opnd loc sn)
  1145.  
  1146.   (cond ((reg? loc)
  1147.          (make-top-of-frame-if-stk-opnd68 opnd sn)
  1148.          (move-opnd68-to-loc68
  1149.            (opnd68->true-opnd68 opnd sn)
  1150.            (reg->reg68 loc)))
  1151.  
  1152.         ((stk? loc)
  1153.          (let* ((loc-slot (stk-num loc))
  1154.                 (sn-after-opnd1 (if (< loc-slot sn) sn (- loc-slot 1))))
  1155.            (if (> current-fs loc-slot)
  1156.              (make-top-of-frame
  1157.                (if (frame-base-rel? opnd)
  1158.                  (let ((opnd-slot (frame-base-rel-slot opnd)))
  1159.                    (if (>= opnd-slot (- loc-slot 1)) opnd-slot loc-slot))
  1160.                  loc-slot)
  1161.                sn-after-opnd1))
  1162.            (let* ((opnd1 (opnd68->true-opnd68 opnd sn-after-opnd1))
  1163.                   (opnd2 (opnd68->true-opnd68 (make-frame-base-rel loc-slot) sn)))
  1164.              (move-opnd68-to-loc68 opnd1 opnd2))))
  1165.  
  1166.         ((glo? loc)
  1167.          (make-top-of-frame-if-stk-opnd68 opnd sn)
  1168.          (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd sn)
  1169.                                (make-glob (glo-name loc))))
  1170.  
  1171.         ((clo? loc)
  1172.          (let ((clo (clo->loc68
  1173.                       loc
  1174.                       (temp-in-opnd68 opnd)
  1175.                       (sn-opnd68 opnd sn))))
  1176.            (make-top-of-frame-if-stk-opnd68 opnd sn)
  1177.            (move-opnd68-to-loc68
  1178.              (opnd68->true-opnd68 opnd sn)
  1179.              clo)))
  1180.  
  1181.         (else
  1182.          (compiler-internal-error
  1183.            "move-opnd68-to-loc, unknown 'loc':" loc))))
  1184.  
  1185. ; (move-opnd-to-loc68 opnd loc68 sn) generates the code to copy the value
  1186. ; from PVM operand 'opnd' to the M68000 location 'loc68'.
  1187.  
  1188. (define (move-opnd-to-loc68 opnd loc68 sn)
  1189.   (if (and (lbl? opnd) (areg? loc68))
  1190.  
  1191.     (emit-lea (make-pcr (lbl-num opnd) 0) loc68)
  1192.  
  1193.     (let* ((sn-after-opnd68 (sn-opnd68 loc68 sn))
  1194.            (opnd68 (opnd->opnd68 opnd (temp-in-opnd68 loc68) sn-after-opnd68)))
  1195.       (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn)
  1196.       (let* ((opnd68* (opnd68->true-opnd68 opnd68 sn-after-opnd68))
  1197.              (loc68* (opnd68->true-opnd68 loc68 sn)))
  1198.         (move-opnd68-to-loc68 opnd68* loc68*)))))
  1199.  
  1200. ; (touch-reg68-to-reg68 src dst keep) generates the code to touch the
  1201. ; M68000 register 'src' and put the result in the M68000 register 'dst'.
  1202. ; 'keep' (if not #f) is a M68000 register that must not be modified.
  1203.  
  1204. (define (touch-reg68-to-reg68 src dst keep)
  1205.  
  1206.   (define (trap-to-touch-handler dreg keep lbl)
  1207.     (if ofile-stats?
  1208.       (emit-stat '((touch 0 (determined-placeholder -1)
  1209.                             (undetermined-placeholder 1)))))
  1210.     (if keep (begin (emit-move.l keep pdec-sp) (adjust-current-fs 1)))
  1211.     (gen-trap instr-source entry-frame #t dreg (+ TOUCH-trap (dreg-num dreg)) lbl)
  1212.     (if keep (begin (emit-move.l pinc-sp keep) (adjust-current-fs -1))))
  1213.  
  1214.   (define (touch-dreg-to-reg src dst keep)
  1215.     (let ((lbl1 (new-lbl!))
  1216. ;          (lbl2 (new-lbl!))
  1217.           (areg (pick-atemp keep)))
  1218.       (emit-btst   src placeholder-reg)
  1219.       (emit-bne    lbl1)
  1220.       (if ofile-stats?
  1221.         (emit-stat '((touch 0 (non-placeholder -1)
  1222.                               (determined-placeholder 1)))))
  1223. ;      (emit-move.l src areg)
  1224. ;      (emit-move.l (make-disp* areg (- type-PLACEHOLDER)) dst)
  1225. ;      (emit-cmp.l  dst (if (dreg? dst) areg src))
  1226. ;      (emit-bne    lbl2)
  1227.       (trap-to-touch-handler src keep lbl1)
  1228.       (move-opnd68-to-loc68 src dst)
  1229. ;      (emit-label  lbl2)
  1230. ))
  1231.  
  1232.   (define (touch-areg-to-dreg src dst keep)
  1233.     (let ((lbl1 (new-lbl!)))
  1234.       (emit-move.l src dst)
  1235.       (emit-btst   dst placeholder-reg)
  1236.       (emit-bne    lbl1)
  1237.       (if ofile-stats?
  1238.         (emit-stat '((touch 0 (non-placeholder -1)
  1239.                               (determined-placeholder 1)))))
  1240. ;      (emit-move.l (make-disp* src (- type-PLACEHOLDER)) dst)
  1241. ;      (emit-cmp.l  src dst)
  1242. ;      (emit-bne    lbl1)
  1243.       (trap-to-touch-handler dst keep lbl1)))
  1244.  
  1245.   (if ofile-stats? (emit-stat '((touch 1 (non-placeholder 1)))))
  1246.  
  1247.   (cond ((dreg? src)
  1248.          (touch-dreg-to-reg src dst keep))
  1249.  
  1250.         ((dreg? dst)
  1251.          (touch-areg-to-dreg src dst keep))
  1252.  
  1253.         ((and keep (identical-opnd68? dtemp1 keep))
  1254.          (emit-exg src dtemp1)
  1255.          (touch-dreg-to-reg dtemp1 dst src)
  1256.          (emit-exg src dtemp1))
  1257.  
  1258.         (else
  1259.          (emit-move.l src dtemp1)
  1260.          (touch-dreg-to-reg dtemp1 dst keep))))
  1261.  
  1262. ; (touch-opnd-to-any-reg68 touch-opnd keep sn) generates the code to touch a
  1263. ; PVM 'potentially future' operand and put the result in any M68000 register.
  1264.  
  1265. (define (touch-opnd-to-any-reg68 touch-opnd keep sn)
  1266.   (let ((loc touch-opnd))
  1267.     (if (reg? loc)
  1268.  
  1269.       (let ((reg (reg->reg68 loc)))
  1270.         (touch-reg68-to-reg68 reg reg keep)
  1271.         reg)
  1272.  
  1273.       (let ((reg (if (and keep (identical-opnd68? keep dtemp1)) atemp1 dtemp1))
  1274.             (opnd (opnd->opnd68 loc keep sn)))
  1275.         (make-top-of-frame-if-stk-opnd68 opnd sn)
  1276.         (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd sn) reg)
  1277.         (touch-reg68-to-reg68 reg reg keep)
  1278.         reg))))
  1279.  
  1280. ; (copy-opnd-to-loc opnd loc sn) generates the code to copy the value
  1281. ; from PVM operand 'opnd' to PVM location 'loc'.
  1282.  
  1283. (define (copy-opnd-to-loc opnd loc sn)
  1284.   (if (and (lbl? opnd) (eq? loc return-reg))
  1285.  
  1286.     (emit-lea (make-pcr (lbl-num opnd) 0) (reg->reg68 loc))
  1287.  
  1288.     (move-opnd68-to-loc
  1289.       (opnd->opnd68 opnd #f (sn-opnd loc sn))
  1290.       loc
  1291.       sn)))
  1292.  
  1293. ; (touch-opnd-to-loc opnd loc sn) generates the code to copy the actual
  1294. ; value from PVM operand 'opnd' to PVM location 'loc', touching 'opnd'
  1295. ; if needed.
  1296.  
  1297. (define (touch-opnd-to-loc opnd loc sn)
  1298.   (if (pot-fut? opnd)
  1299.     (touch-opnd-to-loc* (strip-pot-fut opnd) loc sn)
  1300.     (copy-opnd-to-loc opnd loc sn)))
  1301.  
  1302. (define (touch-opnd-to-loc* opnd loc sn)
  1303.   (if (reg? opnd)
  1304.  
  1305.     (let ((reg68 (reg->reg68 opnd)))
  1306.       (if (reg? loc)
  1307.  
  1308.         (touch-reg68-to-reg68 reg68 (reg->reg68 loc) #f)
  1309.  
  1310.         (begin
  1311.           (touch-reg68-to-reg68 reg68 reg68 #f)
  1312.           (move-opnd68-to-loc reg68 loc sn))))
  1313.  
  1314.     (if (reg? loc)
  1315.  
  1316.       (let ((reg68 (reg->reg68 loc)))
  1317.         (move-opnd-to-loc68 opnd reg68 sn)
  1318.         (touch-reg68-to-reg68 reg68 reg68 #f))
  1319.  
  1320.       (let ((reg68 (touch-opnd-to-any-reg68 opnd #f sn)))
  1321.         (move-opnd68-to-loc reg68 loc sn)))))
  1322.  
  1323. ; (touch-operands opnds touching-pattern sn) transforms all the 'touch
  1324. ; operands' in 'opnds' into plain (non-touching) operands.  Only the
  1325. ; operands specified in 'touching-pattern' will be touched.
  1326.  
  1327. (define (touch-operands opnds touching-pattern sn)
  1328.  
  1329.   (define (touch-operands* opnds i sn)
  1330.     (if (null? opnds)
  1331.       '()
  1332.       (let ((rest (touch-operands* (cdr opnds) (+ i 1) sn))
  1333.             (opnd (car opnds)))
  1334.         (if (pattern-member? i touching-pattern)
  1335.           (cons (touch-operand opnd (sn-opnds rest sn)) rest)
  1336.           (cons (remove-touching opnd (sn-opnds rest sn)) rest)))))
  1337.  
  1338.   (touch-operands* opnds 1 (sn-opnds opnds sn)))
  1339.  
  1340. (define (remove-touching opnd sn)
  1341.   (cond ((clo? opnd)
  1342.          (make-clo (touch-operand (clo-base opnd) sn)
  1343.                    (clo-index opnd)))
  1344.         (else
  1345.          (strip-pot-fut opnd))))
  1346.  
  1347. (define (touch-operand opnd sn)
  1348.   (if (pot-fut? opnd)
  1349.     (let* ((loc (strip-pot-fut opnd))
  1350.            (x (if (or (reg? loc) (stk? loc)) loc (make-stk (+ sn 1)))))
  1351.       (touch-opnd-to-loc* loc x (sn-opnd x sn))
  1352.       x)
  1353.     (remove-touching opnd sn)))
  1354.  
  1355. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1356.  
  1357. (define (gen-trap source frame save-live? not-save-reg num lbl)
  1358.  
  1359.   (define (adjust-slots l n)
  1360.     (cond ((= n 0) (append l '()))
  1361.           ((< n 0) (adjust-slots (cdr l) (+ n 1)))
  1362.           (else    (adjust-slots (cons empty-var l) (- n 1)))))
  1363.  
  1364.   (define (set-slot! slots i x)
  1365.     (let loop ((l slots) (n (- (length slots) i)))
  1366.       (if (> n 0)
  1367.         (loop (cdr l) (- n 1))
  1368.         (set-car! l x))))
  1369.  
  1370.   (let ((ret-slot (frame-first-empty-slot frame)))
  1371.     (let loop1 ((save1 '())
  1372.                 (save2 #f)
  1373.                 (regs (frame-regs frame))
  1374.                 (i 0))
  1375.       (if (pair? regs)
  1376.         (let ((var (car regs)))
  1377.           (if (eq? var ret-var) ; make sure return address is on stack
  1378.             (let ((x (cons (reg->reg68 (make-reg i)) var)))
  1379.               (if (> ret-slot current-fs)
  1380.                 (loop1 (cons x save1) save2 (cdr regs) (+ i 1))
  1381.                 (loop1 save1 x (cdr regs) (+ i 1))))
  1382.             (if (and save-live?
  1383.                      (frame-live? var frame)
  1384.                      (not (eqv? not-save-reg (reg->reg68 (make-reg i)))))
  1385.               (loop1 (cons (cons (reg->reg68 (make-reg i)) var) save1)
  1386.                      save2
  1387.                      (cdr regs)
  1388.                      (+ i 1))
  1389.               (loop1 save1
  1390.                      save2
  1391.                      (cdr regs)
  1392.                      (+ i 1)))))
  1393.         (let ((order (sort-list save1 (lambda (x y) (< (car x) (car y))))))
  1394.           (let ((slots (append (map cdr order)
  1395.                                (adjust-slots (frame-slots frame)
  1396.                                              (- current-fs
  1397.                                                 (frame-size frame)))))
  1398.                 (reg-list (map car order))
  1399.                 (nb-regs (length order)))
  1400.  
  1401.             (define (trap)
  1402.               (emit-trap2 num '())
  1403.               (gen-label-return* (new-lbl!)
  1404.                                  (add-first-class-label! source slots frame)
  1405.                                  slots
  1406.                                  0))
  1407.  
  1408.             (if save2
  1409.               (begin
  1410.                 (emit-move.l
  1411.                   (car save2)
  1412.                   (make-disp* sp-reg (* pointer-size (- current-fs ret-slot))))
  1413.                 (set-slot! slots ret-slot (cdr save2))))
  1414.  
  1415.             (if (> (length order) 2)
  1416.               (begin
  1417.                 (emit-movem.l reg-list pdec-sp)
  1418.                 (trap)
  1419.                 (emit-movem.l pinc-sp reg-list))
  1420.               (let loop2 ((l (reverse reg-list)))
  1421.                 (if (pair? l)
  1422.                   (let ((reg (car l)))
  1423.                     (emit-move.l reg pdec-sp)
  1424.                     (loop2 (cdr l))
  1425.                     (emit-move.l pinc-sp reg))
  1426.                   (trap))))
  1427.  
  1428.             (if save2
  1429.               (emit-move.l
  1430.                 (make-disp* sp-reg (* pointer-size (- current-fs ret-slot)))
  1431.                 (car save2)))
  1432.  
  1433.             (emit-label lbl)))))))
  1434.  
  1435. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1436.  
  1437. (define (gen-LABEL-SIMP lbl sn)
  1438.  
  1439.   (if ofile-stats?
  1440.     (begin
  1441.       (stat-clear!)
  1442.       (stat-add! '(pvm-instr label simp) 1)))
  1443.  
  1444.   (set! pointers-allocated 0)
  1445.  
  1446.   (emit-label lbl))
  1447.  
  1448. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1449.  
  1450. (define (gen-LABEL-PROC lbl nb-parms min rest? closed? sn)
  1451.  
  1452.   (if ofile-stats?
  1453.     (begin
  1454.       (stat-clear!)
  1455.       (stat-add! (list 'pvm-instr
  1456.                        'label
  1457.                        'proc
  1458.                        nb-parms
  1459.                        min
  1460.                        (if rest? 'rest 'not-rest)
  1461.                        (if closed? 'closed 'not-closed))
  1462.                  1)))
  1463.  
  1464.   (set! pointers-allocated 0)
  1465.  
  1466.   (let ((label-descr (add-first-class-label! instr-source '() exit-frame)))
  1467.     (if (= lbl entry-lbl-num)
  1468.       (emit-label lbl)
  1469.       (emit-label-subproc lbl entry-lbl-num label-descr)))
  1470.  
  1471.   (let* ((nb-parms* (if rest? (- nb-parms 1) nb-parms))
  1472.          (dispatch-lbls (make-vector (+ (- nb-parms min) 1)))
  1473.          (optional-lbls (make-vector (+ (- nb-parms min) 1))))
  1474.  
  1475.     (let loop ((i min))
  1476.       (if (<= i nb-parms)
  1477.         (let ((lbl (new-lbl!)))
  1478.           (vector-set! optional-lbls (- nb-parms i) lbl)
  1479.           (vector-set! dispatch-lbls (- nb-parms i)
  1480.             (if (or (>= i nb-parms) (<= nb-parms nb-arg-regs)) lbl (new-lbl!)))
  1481.           (loop (+ i 1)))))
  1482.  
  1483.     ; get closure pointer into the correct PVM register
  1484.  
  1485.     (if closed?
  1486.       (let ((closure-reg (reg-num->reg68 (+ nb-arg-regs 1))))
  1487.         (emit-move.l pinc-sp closure-reg)
  1488.         (emit-subq.l 6 closure-reg)
  1489.         (if (or (and (<= min 1) (<= 1 nb-parms*))
  1490.                 (and (<= min 2) (<= 2 nb-parms*)))
  1491.           (emit-move.w dtemp1 dtemp1))))
  1492.  
  1493.     ; dispatch on number of arguments passed
  1494.  
  1495.     (if (and (<= min 2) (<= 2 nb-parms*))
  1496.       (emit-beq (vector-ref dispatch-lbls (- nb-parms 2))))
  1497.  
  1498.     (if (and (<= min 1) (<= 1 nb-parms*))
  1499.       (emit-bmi (vector-ref dispatch-lbls (- nb-parms 1))))
  1500.  
  1501.     (let loop ((i min))
  1502.       (if (<= i nb-parms*)
  1503.         (begin
  1504.           (if (not (or (= i 1) (= i 2)))
  1505.             (begin
  1506.               (emit-cmp.w (make-imm (encode-arg-count i)) arg-count-reg)
  1507.               (emit-beq (vector-ref dispatch-lbls (- nb-parms i)))))
  1508.           (loop (+ i 1)))))
  1509.  
  1510.     ; trap to a handler if wrong number of args (or rest param not null)
  1511.  
  1512.     (cond (rest?
  1513.            (emit-trap1
  1514.              (if closed? rest-params-closed-trap rest-params-trap)
  1515.              (list min nb-parms*))
  1516.            (if (not closed?) (emit-lbl-ptr lbl))
  1517.            (set! pointers-allocated 1)
  1518.            (gen-guarantee-fudge)
  1519.            (emit-bra (vector-ref optional-lbls 0)))
  1520.           ((= min nb-parms*)
  1521.            (emit-trap1
  1522.              (if closed? wrong-nb-arg1-closed-trap wrong-nb-arg1-trap)
  1523.              (list nb-parms*))
  1524.            (if (not closed?) (emit-lbl-ptr lbl)))
  1525.           (else
  1526.            (emit-trap1
  1527.              (if closed? wrong-nb-arg2-closed-trap wrong-nb-arg2-trap)
  1528.              (list min nb-parms*))
  1529.            (if (not closed?) (emit-lbl-ptr lbl))))
  1530.  
  1531.     ; for each valid argument count with at least one optional, move
  1532.     ; arguments to correct parameter location (only needed if some of
  1533.     ; the parameters end up on the stack)
  1534.  
  1535.     (if (> nb-parms nb-arg-regs)
  1536.       (let loop1 ((i (- nb-parms 1)))
  1537.         (if (>= i min)
  1538.           (let ((nb-stacked (if (<= i nb-arg-regs) 0 (- i nb-arg-regs))))
  1539.             (emit-label (vector-ref dispatch-lbls (- nb-parms i)))
  1540.  
  1541.             (let loop2 ((j 1))
  1542.               (if (and (<= j nb-arg-regs)
  1543.                        (<= j i)
  1544.                        (<= j (- (- nb-parms nb-arg-regs) nb-stacked)))
  1545.                 (begin
  1546.                   (emit-move.l (reg-num->reg68 j) pdec-sp)
  1547.                   (loop2 (+ j 1)))
  1548.                 (let loop3 ((k j))
  1549.                   (if (and (<= k nb-arg-regs) (<= k i))
  1550.                     (begin
  1551.                       (emit-move.l (reg-num->reg68 k)
  1552.                                    (reg-num->reg68 (+ (- k j) 1)))
  1553.                       (loop3 (+ k 1)))))))
  1554.  
  1555.             (if (> i min)
  1556.               (emit-bra (vector-ref optional-lbls (- nb-parms i))))
  1557.             (loop1 (- i 1))))))
  1558.  
  1559.     ; for each valid argument count with at least one optional, set
  1560.     ; that parameter to an unassigned value (or the empty list for the
  1561.     ; rest parameter)
  1562.  
  1563.     (let loop ((i min))
  1564.       (if (<= i nb-parms)
  1565.         (let ((val (if (= i nb-parms*) bits-NULL bits-UNASS)))
  1566.           (emit-label (vector-ref optional-lbls (- nb-parms i)))
  1567.           (cond ((> (- nb-parms i) nb-arg-regs)
  1568.                  (move-n-to-loc68 val pdec-sp))
  1569.                 ((< i nb-parms)
  1570.                  (move-n-to-loc68
  1571.                    val
  1572.                    (reg-num->reg68 (parm->reg-num (+ i 1) nb-parms)))))
  1573.           (loop (+ i 1)))))))
  1574.  
  1575. (define (encode-arg-count n)
  1576.   (cond ((= n 1) -1)
  1577.         ((= n 2) 0)
  1578.         (else    (+ n 1))))
  1579.  
  1580. (define (parm->reg-num i nb-parms)
  1581.   (if (<= nb-parms nb-arg-regs) i (+ i (- nb-arg-regs nb-parms))))
  1582.  
  1583. (define (no-arg-check-entry-offset proc nb-args)
  1584.   (let ((x (proc-obj-call-pat proc)))
  1585.     (if (and (pair? x) (null? (cdr x))) ; proc accepts a fixed nb of args?
  1586.       (let ((arg-count (car x)))
  1587.         (if (= arg-count nb-args)
  1588.           (if (or (= arg-count 1) (= arg-count 2)) 10 14)
  1589.           0))
  1590.       0)))
  1591.  
  1592. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1593.  
  1594. (define (gen-LABEL-RETURN lbl method sn)
  1595.  
  1596.   (if ofile-stats?
  1597.     (begin
  1598.       (stat-clear!)
  1599.       (stat-add! (list 'pvm-instr 'label 'return method) 1)))
  1600.  
  1601.   (set! pointers-allocated 0)
  1602.  
  1603.   (let ((slots (frame-slots exit-frame)))
  1604.  
  1605.     (if (eq? method 'LAZY) ; return of a lazy future
  1606.  
  1607.       (case lazy-task-kind
  1608.  
  1609.         ((MESSAGE-PASSING-LTQ)
  1610.          (set! current-fs (+ current-fs 1))
  1611.          (let ((dummy-lbl (new-lbl!))
  1612.                (skip-lbl (new-lbl!)))
  1613.            (gen-label-return*
  1614.              dummy-lbl
  1615.              (add-first-class-label! instr-source slots exit-frame)
  1616.              slots
  1617.              1)
  1618.            (emit-bra skip-lbl)
  1619.            (gen-label-return-lazy*
  1620.              lbl
  1621.              (add-first-class-label! instr-source slots exit-frame)
  1622.              slots
  1623.              1)
  1624.            (emit-subq.l pointer-size ltq-tail-reg)
  1625.            (emit-label skip-lbl)))
  1626.  
  1627.         ((MESSAGE-PASSING-MIN)
  1628.          (let ((dummy-lbl (new-lbl!)))
  1629.            (gen-label-return*
  1630.              dummy-lbl
  1631.              (add-first-class-label! instr-source slots exit-frame)
  1632.              slots
  1633.              0)
  1634.            (emit-bra lbl)
  1635.            (gen-label-return-lazy*
  1636.              lbl
  1637.              (add-first-class-label! instr-source slots exit-frame)
  1638.              slots
  1639.              0)))
  1640.  
  1641.         ((SHARED-MEMORY)
  1642.          (set! current-fs (+ current-fs 1))
  1643.          (let ((conflict-lbl (new-lbl!))
  1644.                (dummy-lbl (new-lbl!))
  1645.                (skip-lbl (new-lbl!)))
  1646.            (emit-label conflict-lbl)
  1647.            (emit-trap1 steal-conflict-trap '())
  1648.            (gen-label-return*
  1649.              dummy-lbl
  1650.              (add-first-class-label! instr-source slots exit-frame)
  1651.              slots
  1652.              1)
  1653.            (emit-bra skip-lbl)
  1654.            (gen-label-return-lazy*
  1655.              lbl
  1656.              (add-first-class-label! instr-source slots exit-frame)
  1657.              slots
  1658.              1)
  1659.            (emit-clr.l (make-pdec ltq-tail-reg))
  1660.            (emit-cmp.l ltq-head-slot ltq-tail-reg)
  1661.            (emit-bcs   conflict-lbl)
  1662.            (emit-label skip-lbl)
  1663. ;           (emit-move.w false-reg (make-pdec ltq-tail-reg))
  1664. ;           (emit-move.w (make-pdec ltq-tail-reg) dtemp1)
  1665. ;           (emit-beq conflict-lbl)
  1666. ))
  1667.  
  1668.         (else
  1669.          (compiler-internal-error
  1670.            "gen-label-return, unknown 'lazy-task-kind':" lazy-task-kind)))
  1671.  
  1672.       (gen-label-return*
  1673.         lbl
  1674.         (add-first-class-label! instr-source slots exit-frame)
  1675.         slots
  1676.         0))))
  1677.  
  1678. (define (gen-label-return* lbl label-descr slots extra)
  1679.   (let ((i (pos-in-list ret-var slots)))
  1680.     (if i
  1681.       (let* ((fs (length slots))
  1682.              (link (- fs i)))
  1683.         (emit-label-return lbl entry-lbl-num (+ fs extra) link label-descr))
  1684.       (compiler-internal-error
  1685.         "gen-label-return*, no return address in frame"))))
  1686.  
  1687. (define (gen-label-return-lazy* lbl label-descr slots extra)
  1688.   (let ((i (pos-in-list ret-var slots)))
  1689.     (if i
  1690.       (let* ((fs (length slots))
  1691.              (link (- fs i)))
  1692.         (emit-label-return-lazy lbl entry-lbl-num (+ fs extra) link label-descr))
  1693.       (compiler-internal-error
  1694.         "gen-label-return-lazy*, no return address in frame"))))
  1695.  
  1696. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1697.  
  1698. (define (gen-LABEL-TASK lbl method sn)
  1699.  
  1700.   (define (build-delay ret-lbl)
  1701.     (gen-trap instr-source exit-frame #t #f delay-future-trap ret-lbl))
  1702.  
  1703.   (define (build-eager ret-lbl)
  1704.     (gen-trap instr-source exit-frame #t #f eager-future-trap ret-lbl))
  1705.  
  1706.   (define (build-lazy)
  1707.     (case lazy-task-kind
  1708.  
  1709.       ((MESSAGE-PASSING-LTQ SHARED-MEMORY)
  1710.        (if (= current-fs 0)
  1711.  
  1712.          (begin
  1713.            (emit-move.l (reg->reg68 return-reg) pdec-sp)
  1714.            (emit-move.l sp-reg (make-pinc ltq-tail-reg)))
  1715.  
  1716.          (begin
  1717.            (emit-move.l sp-reg atemp1)
  1718.            (emit-move.l (make-pinc atemp1) pdec-sp)
  1719.            (let loop ((i (- current-fs 1)))
  1720.              (if (> i 0)
  1721.                (begin
  1722.                  (emit-move.l (make-pinc atemp1) (make-disp atemp1 -8))
  1723.                  (loop (- i 1)))))
  1724.            (emit-move.l (reg->reg68 return-reg) (make-pdec atemp1))
  1725.            (emit-move.l atemp1 (make-pinc ltq-tail-reg)))))
  1726.  
  1727.       ((MESSAGE-PASSING-MIN)
  1728.        (emit-move.l false-reg ltq-tail-reg))
  1729.  
  1730.       (else
  1731.        (compiler-internal-error
  1732.          "gen-label-task, unknown 'lazy-task-kind':" lazy-task-kind))))
  1733.  
  1734.   (if ofile-stats?
  1735.     (begin
  1736.       (stat-clear!)
  1737.       (stat-add! (list 'pvm-instr 'label 'task method) 1)))
  1738.  
  1739.   (set! pointers-allocated 0)
  1740.  
  1741.   (emit-label lbl)
  1742.  
  1743.   (case method
  1744.     ((DELAY)
  1745.      (build-delay (new-lbl!)))
  1746.     ((EAGER)
  1747.      (build-eager (new-lbl!)))
  1748.     ((EAGER-INLINE)
  1749.      (let ((ret-lbl (new-lbl!)))
  1750.        (emit-cmp.l workq-head-slot null-reg)
  1751.        (emit-bne ret-lbl)
  1752.        (build-eager ret-lbl)))
  1753.     ((LAZY)
  1754.      (build-lazy))
  1755.     (else
  1756.      (compiler-internal-error
  1757.        "gen-LABEL-TASK, unknown task 'method':"
  1758.        method))))
  1759.  
  1760. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1761.  
  1762. (define (gen-APPLY prim opnds loc sn)
  1763.  
  1764.   (if ofile-stats?
  1765.     (begin
  1766.       (stat-add! (list 'pvm-instr
  1767.                        'apply
  1768.                        (string->canonical-symbol (proc-obj-name prim))
  1769.                        (map opnd-stat opnds)
  1770.                        (if loc (opnd-stat loc) #f))
  1771.                  1)
  1772.       (for-each fetch-stat-add! opnds)
  1773.       (if loc (store-stat-add! loc))))
  1774.  
  1775.   (let ((x (proc-obj-inlinable prim)))
  1776.     (if (not x)
  1777.       (compiler-internal-error "gen-APPLY, unknown 'prim':" prim)
  1778.       (if (or (needed? loc sn) (car x)) ; only inline primitive if result
  1779.         ((cdr x) opnds loc sn)))))      ; needed or prim. causes side effects?
  1780.  
  1781. (define (define-APPLY name side-effects? proc)
  1782.   (let ((prim (get-prim-info name)))
  1783.     (proc-obj-inlinable-set! prim (cons side-effects? proc))))
  1784.  
  1785. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1786.  
  1787. (define (gen-COPY opnd loc sn)
  1788.  
  1789.   (if ofile-stats?
  1790.     (begin
  1791.       (stat-add! (list 'pvm-instr 'copy (opnd-stat opnd) (opnd-stat loc)) 1)
  1792.       (fetch-stat-add! opnd)
  1793.       (store-stat-add! loc)))
  1794.  
  1795.   (if (needed? loc sn)
  1796.     (copy-opnd-to-loc opnd loc sn)))
  1797.  
  1798. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1799.  
  1800. (define (gen-MAKE_CLOSURES parms sn)
  1801.  
  1802.   (define (remove-touching-on-parms parms sn)
  1803.     (if (null? parms)
  1804.       '()
  1805.       (let* ((parm (car parms))
  1806.              (rest (remove-touching-on-parms (cdr parms) sn))
  1807.              (opnds (apply append (map (lambda (parm)
  1808.                                          (cons (closure-parms-loc parm)
  1809.                                                (closure-parms-opnds parm)))
  1810.                                        rest))))
  1811.         (cons (make-closure-parms
  1812.                 (remove-touching (closure-parms-loc parm)
  1813.                                  (sn-opnds opnds sn))
  1814.                 (closure-parms-lbl parm)
  1815.                 (closure-parms-opnds parm))
  1816.               rest))))
  1817.  
  1818.   (define (size->bytes size) ; must round to a cache line
  1819.     (* (quotient (+ (* (+ size 2) pointer-size)
  1820.                     (- cache-line-length 1))
  1821.                  cache-line-length)
  1822.        cache-line-length))
  1823.  
  1824.   (define (parms->bytes parms)
  1825.     (if (null? parms)
  1826.       0
  1827.       (+ (size->bytes (length (closure-parms-opnds (car parms))))
  1828.          (parms->bytes (cdr parms)))))
  1829.  
  1830.   (if ofile-stats?
  1831.     (begin
  1832.       (for-each (lambda (x)
  1833.                   (stat-add! (list 'pvm-instr
  1834.                                    'make_closure
  1835.                                    (opnd-stat (closure-parms-loc x))
  1836.                                    (map opnd-stat (closure-parms-opnds x)))
  1837.                              1)
  1838.                   (store-stat-add! (closure-parms-loc x))
  1839.                   (fetch-stat-add! (make-lbl (closure-parms-lbl x)))
  1840.                   (for-each fetch-stat-add! (closure-parms-opnds x)))
  1841.                 parms)))
  1842.  
  1843.   (let ((total-space-needed (parms->bytes parms))
  1844.         (lbl1 (new-lbl!)))
  1845.  
  1846.     (emit-move.l closure-ptr-slot atemp2)
  1847.     (move-n-to-loc68 total-space-needed dtemp1)
  1848.     (emit-sub.l dtemp1 atemp2)
  1849.     (emit-cmp.l closure-lim-slot atemp2)
  1850.     (emit-bcc   lbl1)
  1851.     (gen-trap instr-source entry-frame #f #f closure-alloc-trap lbl1)
  1852.     (emit-move.l atemp2 closure-ptr-slot)
  1853.  
  1854.     (let* ((parms* (remove-touching-on-parms parms sn))
  1855.            (opnds* (apply append (map closure-parms-opnds parms*)))
  1856.            (sn* (sn-opnds opnds* sn)))
  1857.  
  1858.       (let loop1 ((parms parms*))
  1859.         (let ((loc  (closure-parms-loc (car parms)))
  1860.               (size (length (closure-parms-opnds (car parms))))
  1861.               (rest (cdr parms)))
  1862.           (if (= size 1)
  1863.             (emit-addq.l type-PROCEDURE atemp2)
  1864.             (emit-move.w (make-imm (+ #x8000 (* (+ size 1) 4)))
  1865.                          (make-pinc atemp2)))
  1866.           (move-opnd68-to-loc atemp2 loc (sn-opnds (map closure-parms-loc rest) sn*))
  1867.           (if (null? rest)
  1868.             (add-n-to-loc68 (+ (- (size->bytes size) total-space-needed) 2) atemp2)
  1869.             (begin
  1870.               (add-n-to-loc68 (- (size->bytes size) type-PROCEDURE) atemp2)
  1871.               (loop1 rest)))))
  1872.  
  1873.       (let loop2 ((parms parms*))
  1874.         (let* ((opnds (closure-parms-opnds (car parms)))
  1875.                (lbl   (closure-parms-lbl (car parms)))
  1876.                (size  (length opnds))
  1877.                (rest  (cdr parms)))
  1878.  
  1879.           (emit-lea (make-pcr lbl 0) atemp1)
  1880.           (emit-move.l atemp1 (make-pinc atemp2))
  1881.  
  1882.           (let loop3 ((opnds opnds))
  1883.             (if (not (null? opnds))
  1884.               (let ((sn** (sn-opnds (apply append (map closure-parms-opnds rest)) sn)))
  1885.                 (move-opnd-to-loc68 (car opnds)
  1886.                                     (make-pinc atemp2)
  1887.                                     (sn-opnds (cdr opnds) sn**))
  1888.                 (loop3 (cdr opnds)))))
  1889.  
  1890.           (if (not (null? rest))
  1891.             (begin
  1892.               (add-n-to-loc68 (- (size->bytes size) (* (+ size 1) pointer-size)) atemp2)
  1893.               (loop2 rest))))))))
  1894.  
  1895. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1896.  
  1897. (define (gen-COND test opnds true-lbl false-lbl intr-check? next-lbl)
  1898.  
  1899.   (if ofile-stats?
  1900.     (begin
  1901.       (stat-add! (list 'pvm-instr
  1902.                        'cond
  1903.                        (string->canonical-symbol (proc-obj-name test))
  1904.                        (map opnd-stat opnds)
  1905.                        (if intr-check? 'intr-check 'not-intr-check))
  1906.                  1)
  1907.       (for-each fetch-stat-add! opnds)
  1908.       (stat-dump!)))
  1909.  
  1910.   (let ((proc (proc-obj-test test)))
  1911.     (if proc
  1912.       (gen-COND* proc opnds true-lbl false-lbl intr-check? next-lbl)
  1913.       (compiler-internal-error "gen-COND, unknown 'test':" test))))
  1914.  
  1915. (define (gen-COND* proc opnds true-lbl false-lbl intr-check? next-lbl)
  1916.   (let ((fs (frame-size exit-frame)))
  1917.  
  1918.     (define (double-branch)
  1919.       (proc #t opnds false-lbl fs)
  1920.       (if ofile-stats?
  1921.         (emit-stat '((pvm-instr.cond.fall-through 1)
  1922.                      (pvm-instr.cond.double-branch 1))))
  1923.       (emit-bra true-lbl)
  1924.       (gen-deferred-code!))
  1925.  
  1926.     (gen-guarantee-fudge)
  1927.  
  1928.     (if intr-check?
  1929.       (gen-intr-check))
  1930.  
  1931.     (if next-lbl
  1932.       (cond ((= true-lbl next-lbl)
  1933.              (proc #t opnds false-lbl fs)
  1934.              (if ofile-stats?
  1935.                (emit-stat '((pvm-instr.cond.fall-through 1)))))
  1936.             ((= false-lbl next-lbl)
  1937.              (proc #f opnds true-lbl fs)
  1938.              (if ofile-stats?
  1939.                (emit-stat '((pvm-instr.cond.fall-through 1)))))
  1940.             (else
  1941.              (double-branch)))
  1942.       (double-branch))))
  1943.  
  1944. (define (define-COND name proc)
  1945.  
  1946.   (define-APPLY name #f (lambda (opnds loc sn)
  1947.     (let ((true-lbl (new-lbl!))
  1948.           (cont-lbl (new-lbl!))
  1949.           (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  1950.                    (reg->reg68 loc)
  1951.                    dtemp1)))
  1952.  
  1953.       (proc #f opnds true-lbl current-fs)
  1954.       (move-n-to-loc68 bits-FALSE reg68)
  1955.       (emit-bra cont-lbl)
  1956.       (emit-label true-lbl)
  1957.       (move-n-to-loc68 bits-TRUE reg68)
  1958.       (emit-label cont-lbl)
  1959.  
  1960.       (move-opnd68-to-loc reg68 loc sn))))
  1961.  
  1962.   (proc-obj-test-set! (get-prim-info name) proc))
  1963.  
  1964. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1965.  
  1966. (define (gen-JUMP opnd nb-args intr-check? next-lbl)
  1967.   (let ((fs (frame-size exit-frame)))
  1968.  
  1969.     (if ofile-stats?
  1970.       (begin
  1971.         (stat-add! (list 'pvm-instr
  1972.                          'jump
  1973.                          (opnd-stat opnd)
  1974.                          nb-args
  1975.                          (if intr-check? 'intr-check 'not-intr-check))
  1976.                    1)
  1977.         (jump-stat-add! opnd)
  1978.         (if (and (lbl? opnd) next-lbl (= next-lbl (lbl-num opnd)))
  1979.           (stat-add! '(pvm-instr.jump.fall-through) 1))
  1980.         (stat-dump!)))
  1981.  
  1982.     (gen-guarantee-fudge)
  1983.     (cond ((glo? opnd)
  1984.            (if intr-check? (gen-intr-check))
  1985.            (setup-jump fs nb-args)
  1986.            (emit-jmp-glob (make-glob (glo-name opnd)))
  1987.            (gen-deferred-code!))
  1988.           ((and (stk? opnd) (= (stk-num opnd) (+ fs 1)) (not nb-args))
  1989.            (if intr-check? (gen-intr-check))
  1990.            (setup-jump (+ fs 1) nb-args)
  1991.            (emit-rts)
  1992.            (gen-deferred-code!))
  1993.           ((lbl? opnd)
  1994.            (if (and intr-check?
  1995.                     (= fs current-fs)
  1996.                     (not nb-args)
  1997.                     (not (and next-lbl (= next-lbl (lbl-num opnd)))))
  1998.              (gen-intr-check-branch (lbl-num opnd))
  1999.              (begin
  2000.                (if intr-check? (gen-intr-check))
  2001.                (setup-jump fs nb-args)
  2002.                (if (not (and next-lbl (= next-lbl (lbl-num opnd))))
  2003.                  (emit-bra (lbl-num opnd))))))
  2004.           ((obj? opnd)
  2005.            (if intr-check? (gen-intr-check))
  2006.            (let ((val (obj-val opnd)))
  2007.              (if (proc-obj? val)
  2008.                (let ((num (add-object val))
  2009.                      (offset (no-arg-check-entry-offset val nb-args)))
  2010.                  (setup-jump fs (if (<= offset 0) nb-args #f))
  2011.                  (if num
  2012.                    (emit-jmp-proc num offset)
  2013.                    (emit-jmp-prim val offset))
  2014.                  (gen-deferred-code!))
  2015.                (gen-JUMP* (opnd->opnd68 opnd #f fs) fs nb-args))))
  2016.           (else
  2017.            (if intr-check? (gen-intr-check))
  2018.            (gen-JUMP* (opnd->opnd68 opnd #f fs) fs nb-args)))))
  2019.  
  2020. (define (gen-JUMP* opnd fs nb-args)
  2021.   (if nb-args
  2022.     (let ((lbl (new-lbl!)))
  2023.       (make-top-of-frame-if-stk-opnd68 opnd fs)
  2024.       (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd fs) atemp1)
  2025.       (shrink-frame fs)
  2026.       (emit-move.l atemp1 dtemp1)
  2027.       (emit-addq.w (modulo (- type-PAIR type-PROCEDURE) 8) dtemp1)
  2028.       (emit-btst   dtemp1 pair-reg)
  2029.       (emit-beq    lbl)
  2030.       (move-n-to-loc68 (encode-arg-count nb-args) arg-count-reg)
  2031.       (emit-trap3 non-proc-jump-trap)
  2032.       (emit-label lbl)
  2033.       (move-n-to-loc68 (encode-arg-count nb-args) arg-count-reg)
  2034.       (emit-jmp (make-ind atemp1)))
  2035.     (let ((areg (move-opnd68-to-any-areg opnd #f fs)))
  2036.       (setup-jump fs nb-args)
  2037.       (emit-jmp (make-ind areg))))
  2038.   (gen-deferred-code!))
  2039.  
  2040. (define (setup-jump fs nb-args)
  2041.   (shrink-frame fs)
  2042.   (if nb-args
  2043.     (move-n-to-loc68 (encode-arg-count nb-args) arg-count-reg)))
  2044.  
  2045. (define (gen-intr-check)
  2046.   (let ((lbl (new-lbl!)))
  2047.     (emit-dbra  intr-timer-reg lbl)
  2048.     (if (not (eq? lazy-task-kind 'SHARED-MEMORY))
  2049.       (emit-move.l ltq-tail-reg ltq-tail-slot))
  2050.     (emit-moveq (- intr-latency 1) intr-timer-reg)
  2051.     (emit-cmp.l intr-flag-slot sp-reg)
  2052.     (emit-bcc   lbl)
  2053.     (gen-trap instr-source entry-frame #f #f intr-trap lbl)))
  2054.  
  2055. (define (gen-intr-check-branch lbl)
  2056.   (emit-dbra  intr-timer-reg lbl)
  2057.   (if (not (eq? lazy-task-kind 'SHARED-MEMORY))
  2058.     (emit-move.l ltq-tail-reg ltq-tail-slot))
  2059.   (emit-moveq (- intr-latency 1) intr-timer-reg)
  2060.   (emit-cmp.l intr-flag-slot sp-reg)
  2061.   (emit-bcc   lbl)
  2062.   (gen-trap instr-source entry-frame #f #f intr-trap (new-lbl!))
  2063.   (emit-bra   lbl))
  2064.  
  2065. ;------------------------------------------------------------------------------
  2066.  
  2067. ; Definitions used for APPLY and COND instructions:
  2068.  
  2069. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2070.  
  2071. ; for inlining reference and assignment to slot of an object
  2072.  
  2073. (define (make-gen-slot-ref slot type)
  2074.   (lambda (opnds loc sn)
  2075.     (let* ((sn-loc (sn-opnd loc sn))
  2076.            (opnd (touch-operand (car opnds) sn-loc)))
  2077.       (move-opnd-to-loc68 opnd atemp1 sn-loc)
  2078.       (move-opnd68-to-loc (make-disp* atemp1 (- (* slot pointer-size) type))
  2079.                           loc
  2080.                           sn))))
  2081.  
  2082. (define (make-gen-slot-set! slot type)
  2083.   (lambda (opnds loc sn)
  2084.     (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2085.            (opnds (touch-operands opnds '(1) sn-loc)))
  2086.       (let* ((first-opnd (car opnds))
  2087.              (second-opnd (cadr opnds))
  2088.              (sn-second-opnd (sn-opnd second-opnd sn-loc)))
  2089.         (move-opnd-to-loc68 first-opnd atemp1 sn-second-opnd)
  2090.         (move-opnd-to-loc68 second-opnd
  2091.                             (make-disp* atemp1 (- (* slot pointer-size) type))
  2092.                             sn-loc)
  2093.         (if loc
  2094.           (if (not (eq? first-opnd loc))
  2095.             (move-opnd68-to-loc atemp1 loc sn)))))))
  2096.  
  2097. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2098.  
  2099. ; for inlining CONS
  2100.  
  2101. (define (gen-cons weak? opnds loc sn)
  2102.   (let* ((sn-loc (sn-opnd loc sn))
  2103.          (opnds (touch-operands opnds '() sn-loc)))
  2104.     (let ((first-opnd (car opnds))
  2105.           (second-opnd (cadr opnds)))
  2106.  
  2107.       (gen-guarantee-space 2)
  2108.  
  2109.       (if (or (contains-opnd? loc second-opnd) (might-touch-opnd? loc) weak?)
  2110.  
  2111.         (let ((sn-second-opnd (sn-opnd second-opnd sn-loc)))
  2112.           (move-opnd-to-loc68 first-opnd (make-pdec heap-reg) sn-second-opnd)
  2113.           (move-opnd68-to-loc68 heap-reg atemp2) ; *** atemp2 should be safe
  2114.           (move-opnd-to-loc68 second-opnd (make-pdec heap-reg) sn-loc)
  2115.           (if weak? (emit-subq.l (modulo (- type-PAIR type-WEAK-PAIR) 8) atemp2))
  2116.           (move-opnd68-to-loc atemp2 loc sn))
  2117.  
  2118.         (let* ((sn-second-opnd (sn-opnd second-opnd sn))
  2119.                (sn-loc (sn-opnd loc sn-second-opnd)))
  2120.           (move-opnd-to-loc68 first-opnd (make-pdec heap-reg) sn-loc)
  2121.           (move-opnd68-to-loc heap-reg loc sn-second-opnd)
  2122.           (move-opnd-to-loc68 second-opnd (make-pdec heap-reg) sn))))))
  2123.  
  2124. ; for inlining of CAR/CDR chains
  2125.  
  2126. (define (make-gen-APPLY-C...R weak? pattern)
  2127.   (lambda (opnds loc sn)
  2128.     (let* ((sn-loc (sn-opnd loc sn))
  2129.            (opnd (touch-operand (car opnds) sn-loc)))
  2130.  
  2131.       (move-opnd-to-loc68 opnd atemp1 sn-loc)
  2132.  
  2133.       (let loop ((pattern pattern))
  2134.         (if (<= pattern 3)
  2135.           (if (= pattern 3)
  2136.             (if weak?
  2137.               (move-opnd68-to-loc (make-disp* atemp1 (- type-WEAK-PAIR)) loc sn)
  2138.               (move-opnd68-to-loc (make-pdec atemp1) loc sn)) ; cdr
  2139.             (if weak?
  2140.               (move-opnd68-to-loc (make-disp* atemp1 (- type-PAIR type-WEAK-PAIR)) loc sn)
  2141.               (move-opnd68-to-loc (make-ind atemp1) loc sn))) ; car
  2142.           (begin
  2143.             (if (odd? pattern)
  2144.               (if weak?
  2145.                 (emit-move.l (make-disp* atemp1 (- type-WEAK-PAIR)) atemp1)
  2146.                 (emit-move.l (make-pdec atemp1) atemp1)) ; cdr
  2147.               (if weak?
  2148.                 (emit-move.l (make-disp* atemp1 (- type-PAIR type-WEAK-PAIR)) atemp1)
  2149.                 (emit-move.l (make-ind atemp1) atemp1))) ; car
  2150.             (if touch-C...R?
  2151.               (touch-reg68-to-reg68 atemp1 atemp1 #f))
  2152.             (loop (quotient pattern 2))))))))
  2153.  
  2154. (define touch-C...R? #t)
  2155.  
  2156. ; for inlining assignments to CAR/CDR
  2157.  
  2158. (define (gen-set-car! weak? opnds loc sn)
  2159.   (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2160.          (opnds (touch-operands opnds '(1) sn-loc)))
  2161.     (let* ((first-opnd (car opnds))
  2162.            (second-opnd (cadr opnds))
  2163.            (sn-second-opnd (sn-opnd second-opnd sn-loc)))
  2164.       (move-opnd-to-loc68 first-opnd atemp1 sn-second-opnd)
  2165.       (if weak?
  2166.         (move-opnd-to-loc68 second-opnd (make-disp* atemp1 (- type-PAIR type-WEAK-PAIR)) sn-loc)
  2167.         (move-opnd-to-loc68 second-opnd (make-ind atemp1) sn-loc))
  2168.       (if (and loc (not (eq? first-opnd loc)))
  2169.         (move-opnd68-to-loc atemp1 loc sn)))))
  2170.  
  2171. (define (gen-set-cdr! weak? opnds loc sn)
  2172.   (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2173.          (opnds (touch-operands opnds '(1) sn-loc)))
  2174.     (let* ((first-opnd (car opnds))
  2175.            (second-opnd (cadr opnds))
  2176.            (sn-second-opnd (sn-opnd second-opnd sn-loc)))
  2177.       (move-opnd-to-loc68 first-opnd atemp1 sn-second-opnd)
  2178.       (if weak?
  2179.         (move-opnd-to-loc68 second-opnd (make-disp* atemp1 (- type-WEAK-PAIR)) sn-loc)
  2180.         (if (and loc (not (eq? first-opnd loc)))
  2181.           (move-opnd-to-loc68 second-opnd (make-disp atemp1 (- pointer-size)) sn-loc)
  2182.           (move-opnd-to-loc68 second-opnd (make-pdec atemp1) sn-loc)))
  2183.       (if (and loc (not (eq? first-opnd loc)))
  2184.         (move-opnd68-to-loc atemp1 loc sn)))))
  2185.  
  2186. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2187.  
  2188. ; for inlining of fixnum arithmetic
  2189.  
  2190. (define (commut-oper gen opnds loc sn self? accum-self accum-other)
  2191.   (if (null? opnds)
  2192.     (gen (reverse accum-self) (reverse accum-other) loc sn self?)
  2193.     (let ((opnd (car opnds))
  2194.           (rest (cdr opnds)))
  2195.       (cond ((and (not self?) (eq? opnd loc))
  2196.              (commut-oper gen rest loc sn #t accum-self accum-other))
  2197.             ((contains-opnd? loc opnd)
  2198.              (commut-oper gen rest loc sn self? (cons opnd accum-self) accum-other))
  2199.             (else
  2200.              (commut-oper gen rest loc sn self? accum-self (cons opnd accum-other)))))))
  2201.  
  2202. (define (gen-add-in-place opnds loc68 sn)
  2203.   (if (not (null? opnds))
  2204.     (let* ((first-opnd (car opnds))
  2205.            (other-opnds (cdr opnds))
  2206.            (sn-other-opnds (sn-opnds other-opnds sn))
  2207.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))
  2208.            (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 loc68) (sn-opnd68 loc68 sn))))
  2209.       (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn-other-opnds)
  2210.       (if (imm? opnd68)
  2211.         (add-n-to-loc68 (imm-val opnd68) (opnd68->true-opnd68 loc68 sn-other-opnds))
  2212.         (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds)))
  2213.           (if (or (dreg? opnd68) (reg68? loc68))
  2214.             (emit-add.l opnd68* (opnd68->true-opnd68 loc68 sn-other-opnds))
  2215.             (begin
  2216.               (move-opnd68-to-loc68 opnd68* dtemp1)
  2217.               (emit-add.l dtemp1 (opnd68->true-opnd68 loc68 sn-other-opnds))))))
  2218.       (gen-add-in-place other-opnds loc68 sn))))
  2219.  
  2220. (define (gen-add self-opnds other-opnds loc sn self?)
  2221.   (let* ((opnds (append self-opnds other-opnds))
  2222.          (first-opnd (car opnds))
  2223.          (other-opnds (cdr opnds))
  2224.          (sn-other-opnds (sn-opnds other-opnds sn))
  2225.          (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)))
  2226.     (if (<= (length self-opnds) 1) ; loc must be reg or stk
  2227.  
  2228.       (let ((loc68 (loc->loc68 loc #f sn-first-opnd)))
  2229.         (if self?
  2230.           (gen-add-in-place opnds loc68 sn)
  2231.           (begin
  2232.             (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds)
  2233.             (gen-add-in-place other-opnds loc68 sn))))
  2234.  
  2235.       (begin
  2236.         (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds))
  2237.         (gen-add-in-place other-opnds dtemp1 (sn-opnd loc sn))
  2238.         (if self?
  2239.           (let ((loc68 (loc->loc68 loc dtemp1 sn)))
  2240.             (make-top-of-frame-if-stk-opnd68 loc68 sn)
  2241.             (emit-add.l dtemp1 (opnd68->true-opnd68 loc68 sn)))
  2242.           (move-opnd68-to-loc dtemp1 loc sn))))))
  2243.  
  2244. (define (gen-sub-in-place opnds loc68 sn)
  2245.   (if (not (null? opnds))
  2246.     (let* ((first-opnd (car opnds))
  2247.            (other-opnds (cdr opnds))
  2248.            (sn-other-opnds (sn-opnds other-opnds sn))
  2249.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))
  2250.            (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 loc68) (sn-opnd68 loc68 sn))))
  2251.       (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn-other-opnds)
  2252.       (if (imm? opnd68)
  2253.         (add-n-to-loc68 (- (imm-val opnd68)) (opnd68->true-opnd68 loc68 sn-other-opnds))
  2254.         (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds)))
  2255.           (if (or (dreg? opnd68) (reg68? loc68))
  2256.             (emit-sub.l opnd68* (opnd68->true-opnd68 loc68 sn-other-opnds))
  2257.             (begin
  2258.               (move-opnd68-to-loc68 opnd68* dtemp1)
  2259.               (emit-sub.l dtemp1 (opnd68->true-opnd68 loc68 sn-other-opnds))))))
  2260.       (gen-sub-in-place other-opnds loc68 sn))))
  2261.  
  2262. (define (gen-sub first-opnd other-opnds loc sn self-opnds?)
  2263.   (if (null? other-opnds) ; we are negating a location
  2264.  
  2265.     (if (and (or (reg? loc) (stk? loc))
  2266.              (not (eq? loc return-reg)))
  2267.  
  2268.       (begin
  2269.         (copy-opnd-to-loc first-opnd loc (sn-opnd loc sn))
  2270.         (let ((loc68 (loc->loc68 loc #f sn)))
  2271.           (make-top-of-frame-if-stk-opnd68 loc68 sn)
  2272.           (emit-neg.l (opnd68->true-opnd68 loc68 sn))))
  2273.  
  2274.       (begin
  2275.         (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn))
  2276.         (emit-neg.l dtemp1)
  2277.         (move-opnd68-to-loc dtemp1 loc sn)))
  2278.  
  2279.     (let* ((sn-other-opnds (sn-opnds other-opnds sn))
  2280.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)))
  2281.  
  2282.       (if (and (not self-opnds?)
  2283.                (or (reg? loc) (stk? loc)))
  2284.  
  2285.         (let ((loc68 (loc->loc68 loc #f sn-first-opnd)))
  2286.           (if (not (eq? first-opnd loc))
  2287.             (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds))
  2288.           (gen-sub-in-place other-opnds loc68 sn))
  2289.  
  2290.         (begin
  2291.           (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds))
  2292.           (gen-sub-in-place other-opnds dtemp1 (sn-opnd loc sn))
  2293.           (move-opnd68-to-loc dtemp1 loc sn))))))
  2294.  
  2295. (define (gen-mul-in-place opnds reg68 sn)
  2296.   (if (not (null? opnds))
  2297.     (let* ((first-opnd (car opnds))
  2298.            (other-opnds (cdr opnds))
  2299.            (sn-other-opnds (sn-opnds other-opnds sn))
  2300.            (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 reg68) sn)))
  2301.       (make-top-of-frame-if-stk-opnd68 opnd68 sn-other-opnds)
  2302.       (if (imm? opnd68)
  2303.         (mul-n-to-reg68 (quotient (imm-val opnd68) 8) reg68)
  2304.         (begin
  2305.           (emit-asr.l (make-imm 3) reg68)
  2306.           (emit-muls.l (opnd68->true-opnd68 opnd68 sn-other-opnds) reg68)))
  2307.       (gen-mul-in-place other-opnds reg68 sn))))
  2308.  
  2309. (define (gen-mul self-opnds other-opnds loc sn self?)
  2310.   (let* ((opnds (append self-opnds other-opnds))
  2311.          (first-opnd (car opnds))
  2312.          (other-opnds (cdr opnds))
  2313.          (sn-other-opnds (sn-opnds other-opnds sn))
  2314.          (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)))
  2315.     (if (null? self-opnds) ; loc must be reg
  2316.  
  2317.       (let ((loc68 (loc->loc68 loc #f sn-first-opnd)))
  2318.         (if self?
  2319.           (gen-mul-in-place opnds loc68 sn)
  2320.           (begin
  2321.             (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds)
  2322.             (gen-mul-in-place other-opnds loc68 sn))))
  2323.  
  2324.       (begin
  2325.         (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds))
  2326.         (gen-mul-in-place other-opnds dtemp1 (sn-opnd loc sn))
  2327.         (if self?
  2328.           (let ((loc68 (loc->loc68 loc dtemp1 sn)))
  2329.             (make-top-of-frame-if-stk-opnd68 loc68 sn)
  2330.             (emit-asr.l (make-imm 3) dtemp1)
  2331.             (emit-muls.l dtemp1 (opnd68->true-opnd68 loc68 sn)))
  2332.           (move-opnd68-to-loc dtemp1 loc sn))))))
  2333.  
  2334. (define (gen-div-in-place opnds reg68 sn)
  2335.   (if (not (null? opnds))
  2336.     (let* ((first-opnd (car opnds))
  2337.            (other-opnds (cdr opnds))
  2338.            (sn-other-opnds (sn-opnds other-opnds sn))
  2339.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))
  2340.            (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 reg68) sn)))
  2341.       (make-top-of-frame-if-stk-opnd68 opnd68 sn-other-opnds)
  2342.       (if (imm? opnd68)
  2343.         (let ((n (quotient (imm-val opnd68) 8)))
  2344.           (div-n-to-reg68 n reg68)
  2345.           (if (> (abs n) 1)
  2346.             (emit-and.w (make-imm -8) reg68)))
  2347.         (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds)))
  2348.           (emit-divsl.l opnd68* reg68 reg68)
  2349.           (emit-asl.l (make-imm 3) reg68)))
  2350.       (gen-div-in-place other-opnds reg68 sn))))
  2351.  
  2352. (define (gen-div first-opnd other-opnds loc sn self-opnds?)
  2353.   (if (null? other-opnds) ; we are inverting a location
  2354.  
  2355.     (begin
  2356.       (move-opnd-to-loc68 first-opnd pdec-sp (sn-opnd loc sn))
  2357.       (emit-moveq 8 dtemp1)
  2358.       (emit-divsl.l pinc-sp dtemp1 dtemp1)
  2359.       (emit-asl.l (make-imm 3) dtemp1)
  2360.       (emit-and.w (make-imm -8) dtemp1)
  2361.       (move-opnd68-to-loc dtemp1 loc sn))
  2362.  
  2363.     (let* ((sn-other-opnds (sn-opnds other-opnds sn))
  2364.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)))
  2365.  
  2366.       (if (and (reg? loc)
  2367.                (not self-opnds?)
  2368.                (not (eq? loc return-reg)))
  2369.  
  2370.         (let ((reg68 (reg->reg68 loc)))
  2371.           (if (not (eq? first-opnd loc))
  2372.             (move-opnd-to-loc68 first-opnd reg68 sn-other-opnds))
  2373.           (gen-div-in-place other-opnds reg68 sn))
  2374.  
  2375.         (begin
  2376.           (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds))
  2377.           (gen-div-in-place other-opnds dtemp1 (sn-opnd loc sn))
  2378.           (move-opnd68-to-loc dtemp1 loc sn))))))
  2379.  
  2380. (define (gen-rem first-opnd second-opnd loc sn)
  2381.   (let* ((sn-loc (sn-opnd loc sn))
  2382.          (sn-second-opnd (sn-opnd second-opnd sn-loc)))
  2383.     (move-opnd-to-loc68 first-opnd dtemp1 sn-second-opnd)
  2384.     (let ((opnd68 (opnd->opnd68 second-opnd #f sn-loc))
  2385.           (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2386.                    (reg->reg68 loc)
  2387.                    false-reg)))
  2388.       (make-top-of-frame-if-stk-opnd68 opnd68 sn-loc)
  2389.       (let ((opnd68* (if (areg? opnd68)
  2390.                        (begin (emit-move.l opnd68 reg68) reg68)
  2391.                        (opnd68->true-opnd68 opnd68 sn-loc))))
  2392.         (emit-divsl.l opnd68* reg68 dtemp1))
  2393.       (move-opnd68-to-loc reg68 loc sn)
  2394.       (if (not (and (reg? loc) (not (eq? loc return-reg))))
  2395.         (emit-move.l (make-imm bits-FALSE) false-reg)))))
  2396.  
  2397. (define (gen-mod first-opnd second-opnd loc sn)
  2398.   (let* ((sn-loc (sn-opnd loc sn))
  2399.          (sn-first-opnd (sn-opnd first-opnd sn-loc))
  2400.          (sn-second-opnd (sn-opnd second-opnd sn-first-opnd))
  2401.          (opnd68 (opnd->opnd68 second-opnd #f sn-second-opnd)))
  2402.  
  2403.     (define (general-case)
  2404.       (let ((lbl1 (new-lbl!))
  2405.             (lbl2 (new-lbl!))
  2406.             (lbl3 (new-lbl!))
  2407.             (opnd68** (opnd68->true-opnd68 opnd68 sn-second-opnd))
  2408.             (opnd68* (opnd68->true-opnd68
  2409.                        (opnd->opnd68 first-opnd #f sn-second-opnd)
  2410.                        sn-second-opnd)))
  2411.         (move-opnd68-to-loc68 opnd68* dtemp1)
  2412.         (move-opnd68-to-loc68 opnd68** false-reg)
  2413.         (emit-divsl.l false-reg false-reg dtemp1) ; false-reg <-- remainder
  2414.         (emit-move.l false-reg false-reg)
  2415.         (emit-beq lbl3) ; done if remainder = 0
  2416.         (move-opnd68-to-loc68 opnd68* dtemp1)
  2417.         (emit-bmi lbl1)
  2418.         (move-opnd68-to-loc68 opnd68** dtemp1)
  2419.         (emit-bpl lbl3)
  2420.         (emit-bra lbl2)
  2421.         (emit-label lbl1)
  2422.         (move-opnd68-to-loc68 opnd68** dtemp1)
  2423.         (emit-bmi lbl3)
  2424.         (emit-label lbl2) ; first and second operand have different signs
  2425.         (emit-add.l dtemp1 false-reg)
  2426.         (emit-label lbl3)
  2427.         (move-opnd68-to-loc false-reg loc sn)
  2428.         (emit-move.l (make-imm bits-FALSE) false-reg)))
  2429.  
  2430.     (make-top-of-frame-if-stk-opnd68 opnd68 sn-first-opnd)
  2431.     (if (imm? opnd68)
  2432.       (let ((n (quotient (imm-val opnd68) 8)))
  2433.         (if (> n 0)
  2434.           (let ((shift (power-of-2 n)))
  2435.             (if shift
  2436.               (let ((reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2437.                              (reg->reg68 loc)
  2438.                              dtemp1)))
  2439.                 (move-opnd-to-loc68 first-opnd reg68 sn-loc)
  2440.                 (emit-and.l (make-imm (* (- n 1) 8)) reg68)
  2441.                 (move-opnd68-to-loc reg68 loc sn))
  2442.               (general-case)))
  2443.           (general-case)))
  2444.       (general-case))))
  2445.  
  2446. (define (gen-op emit-op dst-ok?)
  2447.  
  2448.   (define (gen-op-in-place opnds loc68 sn)
  2449.     (if (not (null? opnds))
  2450.       (let* ((first-opnd (car opnds))
  2451.              (other-opnds (cdr opnds))
  2452.              (sn-other-opnds (sn-opnds other-opnds sn))
  2453.              (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))
  2454.              (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 loc68) (sn-opnd68 loc68 sn))))
  2455.         (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn-other-opnds)
  2456.         (if (imm? opnd68)
  2457.           (emit-op opnd68 (opnd68->true-opnd68 loc68 sn-other-opnds))
  2458.           (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds)))
  2459.             (if (or (dreg? opnd68) (dst-ok? loc68))
  2460.               (emit-op opnd68* (opnd68->true-opnd68 loc68 sn-other-opnds))
  2461.               (begin
  2462.                 (move-opnd68-to-loc68 opnd68* dtemp1)
  2463.                 (emit-op dtemp1 (opnd68->true-opnd68 loc68 sn-other-opnds))))))
  2464.         (gen-op-in-place other-opnds loc68 sn))))
  2465.  
  2466.   (lambda (self-opnds other-opnds loc sn self?)
  2467.     (let* ((opnds (append self-opnds other-opnds))
  2468.            (first-opnd (car opnds))
  2469.            (other-opnds (cdr opnds))
  2470.            (sn-other-opnds (sn-opnds other-opnds sn))
  2471.            (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)))
  2472.       (if (<= (length self-opnds) 1) ; loc must be reg or stk
  2473.  
  2474.         (let ((loc68 (loc->loc68 loc #f sn-first-opnd)))
  2475.           (if self?
  2476.             (gen-op-in-place opnds loc68 sn)
  2477.             (begin
  2478.               (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds)
  2479.               (gen-op-in-place other-opnds loc68 sn))))
  2480.  
  2481.         (begin
  2482.           (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds))
  2483.           (gen-op-in-place other-opnds dtemp1 (sn-opnd loc sn))
  2484.           (if self?
  2485.             (let ((loc68 (loc->loc68 loc dtemp1 sn)))
  2486.               (make-top-of-frame-if-stk-opnd68 loc68 sn)
  2487.               (emit-op dtemp1 (opnd68->true-opnd68 loc68 sn)))
  2488.             (move-opnd68-to-loc dtemp1 loc sn)))))))
  2489.  
  2490. (define gen-logior (gen-op emit-or.l dreg?))
  2491. (define gen-logxor (gen-op emit-eor.l (lambda (x) #f)))
  2492. (define gen-logand (gen-op emit-and.l dreg?))
  2493.  
  2494. (define (gen-shift right-shift)
  2495.  
  2496.   (lambda (opnds loc sn)
  2497.     (let* ((sn-loc (sn-opnd loc sn))
  2498.            (opnds (touch-operands opnds '0 sn-loc)))
  2499.       (let* ((opnd1 (car opnds))
  2500.              (opnd2 (cadr opnds))
  2501.              (sn-opnd1 (sn-opnd opnd1 sn-loc))
  2502.              (o2 (opnd->opnd68 opnd2 #f sn-opnd1)))
  2503.         (make-top-of-frame-if-stk-opnd68 o2 sn-opnd1)
  2504.         (if (imm? o2)
  2505.  
  2506.           (let* ((reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2507.                           (reg->reg68 loc)
  2508.                           dtemp1))
  2509.                  (n (quotient (imm-val o2) 8))
  2510.                 (emit-shft (if (> n 0) emit-lsl.l right-shift)))
  2511.             (move-opnd-to-loc68 opnd1 reg68 sn-loc)
  2512.             (let loop ((i (min (abs n) 29)))
  2513.               (if (> i 0)
  2514.                 (begin (emit-shft (make-imm (min i 8)) reg68) (loop (- i 8)))))
  2515.             (if (< n 0)
  2516.               (emit-and.w (make-imm -8) reg68))
  2517.             (move-opnd68-to-loc reg68 loc sn))
  2518.  
  2519.           (let* ((reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2520.                           (reg->reg68 loc)
  2521.                           dtemp1))
  2522.                  (reg68* (if (and (reg? loc) (not (eq? loc return-reg)))
  2523.                            dtemp1
  2524.                            false-reg))
  2525.                  (lbl1 (new-lbl!))
  2526.                  (lbl2 (new-lbl!)))
  2527.             (emit-move.l (opnd68->true-opnd68 o2 sn-opnd1) reg68*)
  2528.             (move-opnd-to-loc68 opnd1 reg68 sn-loc)
  2529.             (emit-asr.l (make-imm 3) reg68*)
  2530.             (emit-bmi lbl1)
  2531.             (emit-lsl.l reg68* reg68)
  2532.             (emit-bra lbl2)
  2533.             (emit-label lbl1)
  2534.             (emit-neg.l reg68*)
  2535.             (right-shift reg68* reg68)
  2536.             (emit-and.w (make-imm -8) reg68)
  2537.             (emit-label lbl2)
  2538.             (move-opnd68-to-loc reg68 loc sn)
  2539.             (if (not (and (reg? loc) (not (eq? loc return-reg))))
  2540.               (emit-move.l (make-imm bits-FALSE) false-reg))))))))
  2541.  
  2542. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2543.  
  2544. ; FLONUM operation
  2545.  
  2546. (define (flo-oper oper1 oper2 opnds loc sn)
  2547.   (gen-guarantee-space 4) ; make sure there is enough space for flonum
  2548.   (move-opnd-to-loc68 (car opnds) atemp1 (sn-opnds (cdr opnds) (sn-opnd loc sn)))
  2549.   (oper1 (make-disp* atemp1 (- pointer-size type-SUBTYPED)) ftemp1)
  2550.   (let loop ((opnds (cdr opnds)))
  2551.     (if (not (null? opnds))
  2552.       (let* ((opnd (car opnds))
  2553.              (other-opnds (cdr opnds))
  2554.              (sn-other-opnds (sn-opnds other-opnds sn)))
  2555.         (move-opnd-to-loc68 opnd atemp1 sn-other-opnds)
  2556.         (oper2 (make-disp* atemp1 (- pointer-size type-SUBTYPED)) ftemp1)
  2557.         (loop (cdr opnds)))))
  2558.   (add-n-to-loc68 (* -4 pointer-size) heap-reg) ; allocate flonum
  2559.   (emit-move.l (make-imm (+ (* 2 1024) (* subtype-FLONUM 8)))
  2560.                (make-ind heap-reg))
  2561.   (let ((reg68 (if (reg? loc) (reg->reg68 loc) atemp1)))
  2562.     (emit-move.l heap-reg reg68)
  2563.     (emit-addq.l type-SUBTYPED reg68))
  2564.   (emit-fmov.d ftemp1 (make-disp* heap-reg pointer-size))
  2565.   (if (not (reg? loc))
  2566.     (move-opnd68-to-loc atemp1 loc sn)))
  2567.  
  2568. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2569.  
  2570. ; for checking for heap overflow after an allocation
  2571.  
  2572. (define (gen-guarantee-space n) ; n must be <= heap-allocation-fudge
  2573.   (set! pointers-allocated (+ pointers-allocated n))
  2574.   (if (> pointers-allocated heap-allocation-fudge)
  2575.     (begin
  2576.       (gen-guarantee-fudge)
  2577.       (set! pointers-allocated n))))
  2578.  
  2579. (define (gen-guarantee-fudge)
  2580.   (if (> pointers-allocated 0)
  2581.     (let ((lbl (new-lbl!)))
  2582.       (emit-cmp.l heap-lim-slot heap-reg)
  2583.       (emit-bcc   lbl)
  2584.       (gen-trap instr-source entry-frame #f #f heap-alloc1-trap lbl)
  2585.       (set! pointers-allocated 0))))
  2586.  
  2587. (define pointers-allocated '())
  2588.  
  2589. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2590.  
  2591. ; for type and subtype manipulation:
  2592.  
  2593. (define (gen-type opnds loc sn)
  2594.   (let* ((sn-loc (sn-opnd loc sn))
  2595.          (opnd (car opnds))
  2596.          (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2597.                   (reg->reg68 loc)
  2598.                   dtemp1)))
  2599.  
  2600.     (move-opnd-to-loc68 opnd reg68 sn-loc)
  2601.     (emit-and.l (make-imm 7) reg68)
  2602.     (emit-asl.l (make-imm 3) reg68)
  2603.     (move-opnd68-to-loc reg68 loc sn)))
  2604.  
  2605. (define (gen-type-cast opnds loc sn)
  2606.   (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2607.          (opnds (touch-operands opnds '(2) sn-loc)))
  2608.     (let ((first-opnd (car opnds))
  2609.           (second-opnd (cadr opnds)))
  2610.       (let* ((sn-loc (if (and loc (not (eq? first-opnd loc))) sn-loc sn))
  2611.              (o1 (opnd->opnd68 first-opnd #f (sn-opnd second-opnd sn-loc)))
  2612.              (o2 (opnd->opnd68 second-opnd (temp-in-opnd68 o1) sn-loc))
  2613.              (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2614.                       (reg->reg68 loc)
  2615.                       dtemp1)))
  2616.         (make-top-of-frame-if-stk-opnds68 o1 o2 sn-loc)
  2617.         (move-opnd68-to-loc68 (opnd68->true-opnd68 o1 (sn-opnd68 o2 sn-loc)) reg68)
  2618.         (emit-and.w (make-imm -8) reg68)
  2619.         (if (imm? o2)
  2620.           (let ((n (quotient (imm-val o2) 8)))
  2621.             (if (> n 0)
  2622.               (emit-addq.w n reg68)))
  2623.           (begin
  2624.             (move-opnd68-to-loc68 (opnd68->true-opnd68 o2 sn-loc) atemp1)
  2625.             (emit-exg atemp1 reg68)
  2626.             (emit-asr.l (make-imm 3) reg68)
  2627.             (emit-add.l atemp1 reg68)))
  2628.         (move-opnd68-to-loc reg68 loc sn)))))
  2629.  
  2630. (define (gen-subtype opnds loc sn)
  2631.   (let* ((sn-loc (sn-opnd loc sn))
  2632.          (opnd (touch-operand (car opnds) sn-loc))
  2633.          (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2634.                   (reg->reg68 loc)
  2635.                   dtemp1)))
  2636.  
  2637.     (move-opnd-to-loc68 opnd atemp1 sn-loc)
  2638.     (emit-moveq 0 reg68)
  2639.     (emit-move.b (make-ind atemp1) reg68)
  2640.     (move-opnd68-to-loc reg68 loc sn)))
  2641.  
  2642. (define (gen-subtype-set! opnds loc sn)
  2643.   (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2644.          (opnds (touch-operands opnds '0 sn-loc)))
  2645.     (let ((first-opnd (car opnds))
  2646.           (second-opnd (cadr opnds)))
  2647.       (let* ((sn-loc (if (and loc (not (eq? first-opnd loc))) sn-loc sn))
  2648.              (o1 (opnd->opnd68 first-opnd #f (sn-opnd second-opnd sn-loc)))
  2649.              (o2 (opnd->opnd68 second-opnd (temp-in-opnd68 o1) sn-loc)))
  2650.         (make-top-of-frame-if-stk-opnds68 o1 o2 sn-loc)
  2651.         (move-opnd68-to-loc68 (opnd68->true-opnd68 o1 (sn-opnd68 o2 sn-loc)) atemp1)
  2652.         (if (imm? o2)
  2653.           (emit-move.b (make-imm (imm-val o2)) (make-ind atemp1))
  2654.           (begin
  2655.             (move-opnd68-to-loc68 (opnd68->true-opnd68 o2 sn-loc) dtemp1)
  2656.             (emit-move.b dtemp1 (make-ind atemp1))))
  2657.         (if (and loc (not (eq? first-opnd loc)))
  2658.           (move-opnd68-to-loc atemp1 loc sn))))))
  2659.  
  2660. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2661.  
  2662. ; for vector manipulation:
  2663.  
  2664. (define (vector-select kind vector string vector8 vector16)
  2665.   (case kind
  2666.     ((STRING)   string)
  2667.     ((VECTOR8)  vector8)
  2668.     ((VECTOR16) vector16)
  2669.     (else       vector)))
  2670.  
  2671. (define (gen-vector kind)
  2672.   (lambda (opnds loc sn)
  2673.     (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2674.            (opnds (touch-operands opnds '0 sn-loc)))
  2675.       (let* ((n (length opnds))
  2676.              (bytes (+ pointer-size (* (vector-select kind 4 1 1 2) n)))
  2677.              (pointers (* (quotient (+ bytes (- pointer-size 1)) pointer-size)
  2678.                           pointer-size))
  2679.              (adjust (modulo (- bytes) 8)))
  2680.  
  2681.         (gen-guarantee-space pointers)
  2682.  
  2683.         (if (not (= adjust 0)) (emit-subq.l adjust heap-reg))
  2684.  
  2685.         (let loop ((opnds (reverse opnds)))
  2686.           (if (pair? opnds)
  2687.             (let* ((o (car opnds))
  2688.                    (sn-o (sn-opnds (cdr opnds) sn-loc)))
  2689.               (if (eq? kind 'VECTOR)
  2690.                 (move-opnd-to-loc68 o (make-pdec heap-reg) sn-o)
  2691.                 (begin
  2692.                   (move-opnd-to-loc68 o dtemp1 sn-o)
  2693.                   (emit-asr.l (make-imm 3) dtemp1)
  2694.                   (if (eq? kind 'VECTOR16)
  2695.                     (emit-move.w dtemp1 (make-pdec heap-reg))
  2696.                     (emit-move.b dtemp1 (make-pdec heap-reg)))))
  2697.               (loop (cdr opnds)))))
  2698.  
  2699.         (emit-move.l (make-imm (+ (* 256 (- bytes pointer-size))
  2700.                                   (* 8 (if (eq? kind 'VECTOR)
  2701.                                          subtype-VECTOR
  2702.                                          subtype-STRING))))
  2703.                      (make-pdec heap-reg))
  2704.  
  2705.         (if loc
  2706.           (begin
  2707.             (emit-lea (make-disp* heap-reg type-SUBTYPED) atemp2)
  2708.             (move-opnd68-to-loc atemp2 loc sn)))))))
  2709.  
  2710. (define (gen-vector-length kind)
  2711.   (lambda (opnds loc sn)
  2712.     (let* ((sn-loc (sn-opnd loc sn))
  2713.            (opnd (touch-operand (car opnds) sn))
  2714.            (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2715.                     (reg->reg68 loc)
  2716.                     dtemp1)))
  2717.   
  2718.       (move-opnd-to-loc68 opnd atemp1 sn-loc)
  2719.       (move-opnd68-to-loc68 (make-disp* atemp1 (- type-SUBTYPED)) reg68)
  2720.       (emit-lsr.l (make-imm (vector-select kind 7 5 5 6)) reg68)
  2721.       (if (not (eq? kind 'VECTOR))
  2722.         (emit-and.w (make-imm -8) reg68))
  2723.       (move-opnd68-to-loc reg68 loc sn))))
  2724.  
  2725. (define (gen-vector-ref kind)
  2726.   (lambda (opnds loc sn)
  2727.     (let* ((sn-loc (sn-opnd loc sn))
  2728.            (opnds (touch-operands opnds '0 sn-loc)))
  2729.       (let ((first-opnd (car opnds))
  2730.             (second-opnd (cadr opnds))
  2731.             (reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  2732.                      (reg->reg68 loc)
  2733.                      dtemp1)))
  2734.  
  2735.         (let* ((o2 (opnd->opnd68 second-opnd #f (sn-opnd first-opnd sn-loc)))
  2736.                (o1 (opnd->opnd68 first-opnd (temp-in-opnd68 o2) sn-loc)))
  2737.           (make-top-of-frame-if-stk-opnds68 o1 o2 sn-loc)
  2738.           (let* ((offset
  2739.                   (if (eq? kind 'SLOT) 0 (- pointer-size type-SUBTYPED)))
  2740.                  (loc68
  2741.                   (if (imm? o2)
  2742.  
  2743.                     (begin
  2744.                       (move-opnd68-to-loc68
  2745.                         (opnd68->true-opnd68 o1 sn-loc)
  2746.                         atemp1)
  2747.                       (make-disp* atemp1
  2748.                                   (+ (quotient (imm-val o2)
  2749.                                                (vector-select kind 2 8 8 4))
  2750.                                      offset)))
  2751.  
  2752.                       (begin
  2753.                         (move-opnd68-to-loc68
  2754.                           (opnd68->true-opnd68 o2 (sn-opnd68 o1 sn-loc))
  2755.                           dtemp1)
  2756.                         (emit-lsr.l (make-imm (vector-select kind 1 3 3 2))
  2757.                                     dtemp1)
  2758.                         (move-opnd68-to-loc68
  2759.                           (opnd68->true-opnd68 o1 sn-loc)
  2760.                           atemp1)
  2761.                         (if (and (identical-opnd68? reg68 dtemp1)
  2762.                                  (not (memq kind '(VECTOR SLOT))))
  2763.                           (begin
  2764.                             (emit-move.l dtemp1 atemp2)
  2765.                             (make-inx atemp1 atemp2 offset))
  2766.                           (make-inx atemp1 dtemp1 offset))))))
  2767.  
  2768.             (if (not (memq kind '(VECTOR SLOT)))
  2769.               (emit-moveq 0 reg68))
  2770.  
  2771.             (case kind
  2772.               ((STRING VECTOR8) (emit-move.b loc68 reg68))
  2773.               ((VECTOR16)       (emit-move.w loc68 reg68))
  2774.               (else             (emit-move.l loc68 reg68)))
  2775.  
  2776.             (if (not (memq kind '(VECTOR SLOT)))
  2777.               (begin
  2778.                 (emit-asl.l (make-imm 3) reg68)
  2779.                 (if (eq? kind 'STRING)
  2780.                   (emit-addq.w type-SPECIAL reg68))))
  2781.  
  2782.           (move-opnd68-to-loc reg68 loc sn)))))))
  2783.  
  2784. (define (gen-vector-set! kind)
  2785.   (lambda (opnds loc sn)
  2786.     (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2787.            (opnds (touch-operands opnds '0 sn-loc)))
  2788.       (let ((first-opnd (car opnds))
  2789.             (second-opnd (cadr opnds))
  2790.             (third-opnd (caddr opnds)))
  2791.         (let* ((sn-loc (if (and loc (not (eq? first-opnd loc)))
  2792.                          (sn-opnd first-opnd sn-loc)
  2793.                          sn))
  2794.                (sn-third-opnd (sn-opnd third-opnd sn-loc))
  2795.                (o2 (opnd->opnd68 second-opnd #f (sn-opnd first-opnd sn-third-opnd)))
  2796.                (o1 (opnd->opnd68 first-opnd (temp-in-opnd68 o2) sn-third-opnd)))
  2797.           (make-top-of-frame-if-stk-opnds68 o1 o2 sn-third-opnd)
  2798.           (let* ((offset
  2799.                   (if (eq? kind 'SLOT) 0 (- pointer-size type-SUBTYPED)))
  2800.                  (loc68
  2801.                   (if (imm? o2)
  2802.  
  2803.                     (begin
  2804.                       (move-opnd68-to-loc68
  2805.                         (opnd68->true-opnd68 o1 sn-third-opnd)
  2806.                         atemp1)
  2807.                       (make-disp* atemp1
  2808.                                   (+ (quotient (imm-val o2)
  2809.                                                (vector-select kind 2 8 8 4))
  2810.                                      offset)))
  2811.  
  2812.                       (begin
  2813.                         (move-opnd68-to-loc68
  2814.                           (opnd68->true-opnd68 o2 (sn-opnd68 o1 sn-loc))
  2815.                           dtemp1)
  2816.                         (emit-lsr.l (make-imm (vector-select kind 1 3 3 2))
  2817.                                     dtemp1)
  2818.                         (move-opnd68-to-loc68
  2819.                           (opnd68->true-opnd68 o1 sn-loc)
  2820.                           atemp1)
  2821.                         (if (not (memq kind '(VECTOR SLOT)))
  2822.                           (begin
  2823.                             (emit-move.l dtemp1 atemp2)
  2824.                             (make-inx atemp1 atemp2 offset))
  2825.                           (make-inx atemp1 dtemp1 offset))))))
  2826.  
  2827.             (if (memq kind '(VECTOR SLOT))
  2828.               (move-opnd-to-loc68 third-opnd loc68 sn-loc)
  2829.               (begin
  2830.                 (move-opnd-to-loc68 third-opnd dtemp1 sn-loc)
  2831.                 (emit-asr.l (make-imm 3) dtemp1)
  2832.                 (if (eq? kind 'VECTOR16)
  2833.                   (emit-move.w dtemp1 loc68)
  2834.                   (emit-move.b dtemp1 loc68))))
  2835.  
  2836.             (if (and loc (not (eq? first-opnd loc)))
  2837.               (copy-opnd-to-loc first-opnd loc sn))))))))
  2838.  
  2839. (define (gen-vector-shrink! kind)
  2840.   (lambda (opnds loc sn)
  2841.     (let* ((sn-loc (if loc (sn-opnd loc sn) sn))
  2842.            (opnds (touch-operands opnds '0 sn-loc)))
  2843.       (let ((first-opnd (car opnds))
  2844.             (second-opnd (cadr opnds)))
  2845.         (let* ((sn-loc (if (and loc (not (eq? first-opnd loc)))
  2846.                          (sn-opnd first-opnd sn-loc)
  2847.                          sn))
  2848.                (o2 (opnd->opnd68 second-opnd #f (sn-opnd first-opnd sn-loc)))
  2849.                (o1 (opnd->opnd68 first-opnd (temp-in-opnd68 o2) sn-loc)))
  2850.           (make-top-of-frame-if-stk-opnds68 o1 o2 sn-loc)
  2851.           (move-opnd68-to-loc68
  2852.             (opnd68->true-opnd68 o2 (sn-opnd68 o1 sn-loc))
  2853.             dtemp1)
  2854.           (emit-asl.l (make-imm (vector-select kind 7 5 5 6)) dtemp1)
  2855.           (emit-move.l (opnd68->true-opnd68 o1 sn-loc) atemp1)
  2856.           (emit-move.b (make-ind atemp1) dtemp1)
  2857.           (emit-move.l dtemp1 (make-disp* atemp1 (- type-SUBTYPED)))
  2858.           (if (and loc (not (eq? first-opnd loc)))
  2859.             (move-opnd68-to-loc atemp1 loc sn)))))))
  2860.  
  2861. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2862.  
  2863. ; for CONDs that perform equality tests to constants
  2864.  
  2865. (define (gen-eq-test bits not? opnds lbl fs)
  2866.   (gen-compare* (opnd->opnd68 (touch-operand (car opnds) fs) #f fs)
  2867.                 (make-imm bits)
  2868.                 fs)
  2869.   (if not? (emit-bne lbl) (emit-beq lbl)))
  2870.  
  2871. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2872.  
  2873. ; for CONDs that perform comparisons
  2874.  
  2875. (define (gen-compare opnd1 opnd2 fs)
  2876.   (let* ((o1 (opnd->opnd68 opnd1 #f (sn-opnd opnd2 fs)))
  2877.          (o2 (opnd->opnd68 opnd2 (temp-in-opnd68 o1) fs)))
  2878.     (gen-compare* o1 o2 fs)))
  2879.  
  2880. (define (gen-compare* o1 o2 fs)
  2881.   (make-top-of-frame-if-stk-opnds68 o1 o2 fs)
  2882.   (let ((order-1-2
  2883.           (cond ((imm? o1)
  2884.                  (cmp-n-to-opnd68 (imm-val o1)
  2885.                                   (opnd68->true-opnd68 o2 fs)))
  2886.                 ((imm? o2)
  2887.                  (not (cmp-n-to-opnd68 (imm-val o2)
  2888.                                        (opnd68->true-opnd68 o1 fs))))
  2889.                 ((reg68? o1)
  2890.                  (emit-cmp.l (opnd68->true-opnd68 o2 fs) o1)
  2891.                  #f)
  2892.                 ((reg68? o2)
  2893.                  (emit-cmp.l (opnd68->true-opnd68 o1 fs) o2)
  2894.                  #t)
  2895.                 (else
  2896.                  (emit-move.l (opnd68->true-opnd68 o1 (sn-opnd68 o2 fs)) dtemp1)
  2897.                  (emit-cmp.l (opnd68->true-opnd68 o2 fs) dtemp1)
  2898.                  #f))))
  2899.     (shrink-frame fs)
  2900.     order-1-2))
  2901.  
  2902. (define (gen-compares branch< branch>= branch> branch<= not? opnds lbl fs)
  2903.   (gen-compares* gen-compare branch< branch>= branch> branch<= not? opnds lbl fs))
  2904.  
  2905. (define (gen-compares* gen-comp branch< branch>= branch> branch<= not? opnds lbl fs)
  2906.  
  2907.   (define (gen-compare-sequence opnd1 opnd2 rest)
  2908.     (if (null? rest)
  2909.  
  2910.       (if (gen-comp opnd1 opnd2 fs)
  2911.         (if not? (branch<= lbl) (branch> lbl))
  2912.         (if not? (branch>= lbl) (branch< lbl)))
  2913.                    
  2914.       (let ((order-1-2 (gen-comp opnd1 opnd2 (sn-opnd opnd2 (sn-opnds rest fs)))))
  2915.         (if (= current-fs fs) ; no need to adjust size of frame further...
  2916.  
  2917.           (if not?
  2918.             (begin
  2919.               (if order-1-2 (branch<= lbl) (branch>= lbl))
  2920.               (gen-compare-sequence opnd2 (car rest) (cdr rest)))
  2921.             (let ((exit-lbl (new-lbl!)))
  2922.               (if order-1-2 (branch<= exit-lbl) (branch>= exit-lbl))
  2923.               (gen-compare-sequence opnd2 (car rest) (cdr rest))
  2924.               (emit-label exit-lbl)))
  2925.  
  2926.           (if not?
  2927.             (let ((next-lbl (new-lbl!)))
  2928.               (if order-1-2 (branch> next-lbl) (branch< next-lbl))
  2929.               (shrink-frame fs)
  2930.               (emit-bra lbl)
  2931.               (emit-label next-lbl)
  2932.               (gen-compare-sequence opnd2 (car rest) (cdr rest)))
  2933.             (let* ((next-lbl (new-lbl!))
  2934.                    (exit-lbl (new-lbl!)))
  2935.               (if order-1-2 (branch> next-lbl) (branch< next-lbl))
  2936.               (shrink-frame fs)
  2937.               (emit-bra exit-lbl)
  2938.               (emit-label next-lbl)
  2939.               (gen-compare-sequence opnd2 (car rest) (cdr rest))
  2940.               (emit-label exit-lbl)))))))
  2941.  
  2942.   (if (or (null? opnds) (null? (cdr opnds)))
  2943.     (begin
  2944.       (shrink-frame fs)
  2945.       (if (not not?) (emit-bra lbl)))
  2946.     (gen-compare-sequence (car opnds) (cadr opnds) (cddr opnds))))
  2947.  
  2948. (define (gen-compare-flo opnd1 opnd2 fs)
  2949.   (let* ((o1 (opnd->opnd68 opnd1 #f (sn-opnd opnd2 fs)))
  2950.          (o2 (opnd->opnd68 opnd2 (temp-in-opnd68 o1) fs)))
  2951.     (make-top-of-frame-if-stk-opnds68 o1 o2 fs)
  2952.     (emit-move.l (opnd68->true-opnd68 o1 (sn-opnd68 o2 fs)) atemp1)
  2953.     (emit-move.l (opnd68->true-opnd68 o2 fs) atemp2)
  2954.     (emit-fmov.d (make-disp* atemp2 (- pointer-size type-SUBTYPED)) ftemp1)
  2955.     (emit-fcmp.d (make-disp* atemp1 (- pointer-size type-SUBTYPED)) ftemp1)
  2956.     #t))
  2957.  
  2958. (define (gen-compares-flo branch< branch>= branch> branch<= not? opnds lbl fs)
  2959.   (gen-compares* gen-compare-flo branch< branch>= branch> branch<= not? opnds lbl fs))
  2960.  
  2961. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2962.  
  2963. ; for CONDs that just have to test the value's type tag
  2964.  
  2965. (define (gen-type-test tag not? opnds lbl fs)
  2966.   (let ((opnd (touch-operand (car opnds) fs)))
  2967.     (let ((o (opnd->opnd68 opnd #f fs)))
  2968.  
  2969.       (define (mask-test set-reg correction)
  2970.         (emit-btst
  2971.           (if (= correction 0)
  2972.             (if (dreg? o)
  2973.               o
  2974.               (begin
  2975.                 (emit-move.l (opnd68->true-opnd68 o fs) dtemp1)
  2976.                 dtemp1))
  2977.             (begin
  2978.               (if (not (eq? o dtemp1))
  2979.                 (emit-move.l (opnd68->true-opnd68 o fs) dtemp1))
  2980.               (emit-addq.w correction dtemp1)
  2981.               dtemp1))
  2982.           set-reg))
  2983.  
  2984.       (make-top-of-frame-if-stk-opnd68 o fs)
  2985.  
  2986.       (cond ((= tag 0)
  2987.              (if (eq? o dtemp1)
  2988.                (emit-and.w (make-imm 7) dtemp1)
  2989.                (begin
  2990.                  (emit-move.l (opnd68->true-opnd68 o fs) dtemp1)
  2991.                  (emit-and.w (make-imm 7) dtemp1))))
  2992.             ((= tag type-PLACEHOLDER)
  2993.              (mask-test placeholder-reg 0))
  2994.             (else
  2995.              (mask-test pair-reg (modulo (- type-PAIR tag) 8))))
  2996.  
  2997.       (shrink-frame fs)
  2998.       (if not?
  2999.         (emit-bne lbl)
  3000.         (emit-beq lbl)))))
  3001.  
  3002. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3003.  
  3004. ; for CONDs that have to test the type tag of a hunk
  3005.  
  3006. (define (gen-subtype-test type not? opnds lbl fs)
  3007.   (let ((opnd (touch-operand (car opnds) fs)))
  3008.     (let ((o (opnd->opnd68 opnd #f fs))
  3009.           (cont-lbl (new-lbl!)))
  3010.       (make-top-of-frame-if-stk-opnd68 o fs)
  3011.       (if (not (eq? o dtemp1))
  3012.         (emit-move.l (opnd68->true-opnd68 o fs) dtemp1))
  3013.       (emit-move.l dtemp1 atemp1)
  3014.       (emit-addq.w (modulo (- type-PAIR type-SUBTYPED) 8) dtemp1)
  3015.       (emit-btst dtemp1 pair-reg)
  3016.       (shrink-frame fs)
  3017.       (if not?
  3018.         (emit-bne lbl)
  3019.         (emit-bne cont-lbl))
  3020.       (emit-cmp.b (make-imm (* type 8)) (make-ind atemp1))
  3021.       (if not?
  3022.         (emit-bne lbl)
  3023.         (emit-beq lbl))
  3024.       (emit-label cont-lbl))))
  3025.  
  3026. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3027.  
  3028. ; for CONDs that have to test for parity (even/odd)
  3029.  
  3030. (define (gen-even-test not? opnds lbl fs)
  3031.   (move-opnd-to-loc68 (touch-operand (car opnds) fs) dtemp1 fs)
  3032.   (emit-and.w (make-imm 8) dtemp1)
  3033.   (shrink-frame fs)
  3034.   (if not? (emit-bne lbl) (emit-beq lbl)))
  3035.  
  3036. ;------------------------------------------------------------------------------
  3037.  
  3038. ; Operation database:
  3039.  
  3040. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3041.  
  3042. ; some common specializations:
  3043.  
  3044. (define (def-spec name specializer-maker)
  3045.   (let ((proc-name (string->canonical-symbol name)))
  3046.     (let ((proc (prim-info proc-name)))
  3047.       (if proc
  3048.         (proc-obj-specialize-set! proc (specializer-maker proc proc-name))
  3049.         (compiler-internal-error
  3050.           "def-spec, unknown primitive:" name)))))
  3051.  
  3052. (define (safe name)
  3053.   (lambda (proc proc-name)
  3054.     (let ((spec (get-prim-info name)))
  3055.       (lambda (decls) spec))))
  3056.  
  3057. (define (unsafe name)
  3058.   (lambda (proc proc-name)
  3059.     (let ((spec (get-prim-info name)))
  3060.       (lambda (decls) (if (not (safe? decls)) spec proc)))))
  3061.  
  3062. (define (safe-arith fix-name flo-name)
  3063.   (arith #t fix-name flo-name))
  3064.  
  3065. (define (unsafe-arith fix-name flo-name)
  3066.   (arith #f fix-name flo-name))
  3067.  
  3068. (define (arith fix-safe? fix-name flo-name)
  3069.   (lambda (proc proc-name)
  3070.     (let ((fix-spec (if fix-name (get-prim-info fix-name) proc))
  3071.           (flo-spec (if flo-name (get-prim-info flo-name) proc)))
  3072.       (lambda (decls)
  3073.         (let ((arith (arith-implementation proc-name decls)))
  3074.           (cond ((eq? arith FIXNUM-sym)
  3075.                  (if (or fix-safe? (not (safe? decls))) fix-spec proc))
  3076.                 ((eq? arith FLONUM-sym)
  3077.                  (if (not (safe? decls)) flo-spec proc))
  3078.                 (else
  3079.                  proc)))))))
  3080.  
  3081. ;------------------------------------------------------------------------------
  3082.  
  3083. ; Operations:
  3084.  
  3085. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3086.  
  3087. (define-APPLY "##TYPE" #f (lambda (opnds loc sn)
  3088.   (gen-type opnds loc sn)))
  3089.  
  3090. (define-APPLY "##TYPE-CAST" #f (lambda (opnds loc sn)
  3091.   (gen-type-cast opnds loc sn)))
  3092.  
  3093. (define-APPLY "##SUBTYPE" #f (lambda (opnds loc sn)
  3094.   (gen-subtype opnds loc sn)))
  3095.  
  3096. (define-APPLY "##SUBTYPE-SET!" #t (lambda (opnds loc sn)
  3097.   (gen-subtype-set! opnds loc sn)))
  3098.  
  3099. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3100.  
  3101. (define-COND "##NOT" (lambda (not? opnds lbl fs)
  3102.   (gen-eq-test bits-FALSE not? opnds lbl fs)))
  3103.  
  3104. (define-COND "##NULL?" (lambda (not? opnds lbl fs)
  3105.   (gen-eq-test bits-NULL not? opnds lbl fs)))
  3106.  
  3107. (define-COND "##UNASSIGNED?" (lambda (not? opnds lbl fs)
  3108.   (gen-eq-test bits-UNASS not? opnds lbl fs)))
  3109.  
  3110. (define-COND "##UNBOUND?" (lambda (not? opnds lbl fs)
  3111.   (gen-eq-test bits-UNBOUND not? opnds lbl fs)))
  3112.  
  3113. (define-COND "##EQ?" (lambda (not? opnds lbl fs)
  3114.   (gen-compares emit-beq emit-bne emit-beq emit-bne
  3115.                 not?
  3116.                 (touch-operands opnds '0 fs)
  3117.                 lbl
  3118.                 fs)))
  3119.  
  3120. (define-COND "##FIXNUM?" (lambda (not? opnds lbl fs)
  3121.   (gen-type-test type-FIXNUM not? opnds lbl fs)))
  3122.  
  3123. (define-COND "##SPECIAL?" (lambda (not? opnds lbl fs)
  3124.   (gen-type-test type-SPECIAL not? opnds lbl fs)))
  3125.  
  3126. (define-COND "##PAIR?" (lambda (not? opnds lbl fs)
  3127.   (gen-type-test type-PAIR not? opnds lbl fs)))
  3128.  
  3129. (define-COND "##WEAK-PAIR?" (lambda (not? opnds lbl fs)
  3130.   (gen-type-test type-WEAK-PAIR not? opnds lbl fs)))
  3131.  
  3132. (define-COND "##SUBTYPED?" (lambda (not? opnds lbl fs)
  3133.   (gen-type-test type-SUBTYPED not? opnds lbl fs)))
  3134.  
  3135. (define-COND "##PROCEDURE?" (lambda (not? opnds lbl fs)
  3136.   (gen-type-test type-PROCEDURE not? opnds lbl fs)))
  3137.  
  3138. (define-COND "##PLACEHOLDER?" (lambda (not? opnds lbl fs)
  3139.   (gen-type-test type-PLACEHOLDER not? opnds lbl fs)))
  3140.  
  3141. (define-COND "##VECTOR?" (lambda (not? opnds lbl fs)
  3142.   (gen-subtype-test subtype-VECTOR not? opnds lbl fs)))
  3143.  
  3144. (define-COND "##SYMBOL?" (lambda (not? opnds lbl fs)
  3145.   (gen-subtype-test subtype-SYMBOL not? opnds lbl fs)))
  3146.  
  3147. (define-COND "##RATNUM?" (lambda (not? opnds lbl fs)
  3148.   (gen-subtype-test subtype-RATNUM not? opnds lbl fs)))
  3149.  
  3150. (define-COND "##CPXNUM?" (lambda (not? opnds lbl fs)
  3151.   (gen-subtype-test subtype-CPXNUM not? opnds lbl fs)))
  3152.  
  3153. (define-COND "##STRING?" (lambda (not? opnds lbl fs)
  3154.   (gen-subtype-test subtype-STRING not? opnds lbl fs)))
  3155.  
  3156. (define-COND "##BIGNUM?" (lambda (not? opnds lbl fs)
  3157.   (gen-subtype-test subtype-BIGNUM not? opnds lbl fs)))
  3158.  
  3159. (define-COND "##FLONUM?" (lambda (not? opnds lbl fs)
  3160.   (gen-subtype-test subtype-FLONUM not? opnds lbl fs)))
  3161.  
  3162. (define-COND "##CHAR?" (lambda (not? opnds lbl fs)
  3163.   (let ((opnd (touch-operand (car opnds) fs)))
  3164.     (let ((o (opnd->opnd68 opnd #f fs))
  3165.           (cont-lbl (new-lbl!)))
  3166.       (make-top-of-frame-if-stk-opnd68 o fs)
  3167.       (emit-move.l (opnd68->true-opnd68 o fs) dtemp1)
  3168.       (if not?
  3169.         (emit-bmi lbl)
  3170.         (emit-bmi cont-lbl))
  3171.       (emit-addq.w (modulo (- type-PAIR type-SPECIAL) 8) dtemp1)
  3172.       (emit-btst dtemp1 pair-reg)
  3173.       (shrink-frame fs)
  3174.       (if not?
  3175.         (emit-bne lbl)
  3176.         (emit-beq lbl))
  3177.       (emit-label cont-lbl)))))
  3178.  
  3179. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3180.  
  3181. (define-APPLY "##FIXNUM.+" #f (lambda (opnds loc sn)
  3182.  
  3183.   (let* ((sn-loc (sn-opnd loc sn))
  3184.          (opnds (touch-operands opnds '0 sn-loc)))
  3185.     (cond ((null? opnds)
  3186.            (copy-opnd-to-loc (make-obj '0) loc sn))
  3187.           ((null? (cdr opnds))
  3188.            (copy-opnd-to-loc (car opnds) loc sn))
  3189.           ((or (reg? loc) (stk? loc))
  3190.            (commut-oper gen-add opnds loc sn #f '() '()))
  3191.           (else
  3192.            (gen-add opnds '() loc sn #f))))))
  3193.  
  3194. (define-APPLY "##FIXNUM.-" #f (lambda (opnds loc sn)
  3195.  
  3196.   (let* ((sn-loc (sn-opnd loc sn))
  3197.          (opnds (touch-operands opnds '0 sn-loc)))
  3198.     (gen-sub (car opnds) (cdr opnds) loc sn (any-contains-opnd? loc (cdr opnds))))))
  3199.  
  3200. (define-APPLY "##FIXNUM.*" #f (lambda (opnds loc sn)
  3201.  
  3202.   (let* ((sn-loc (sn-opnd loc sn))
  3203.          (opnds (touch-operands opnds '0 sn-loc)))
  3204.     (cond ((null? opnds)
  3205.            (copy-opnd-to-loc (make-obj '1) loc sn))
  3206.           ((null? (cdr opnds))
  3207.            (copy-opnd-to-loc (car opnds) loc sn))
  3208.           ((and (reg? loc) (not (eq? loc return-reg)))
  3209.            (commut-oper gen-mul opnds loc sn #f '() '()))
  3210.           (else
  3211.            (gen-mul opnds '() loc sn #f))))))
  3212.  
  3213. (define-APPLY "##FIXNUM.QUOTIENT" #f (lambda (opnds loc sn)
  3214.  
  3215.   (let* ((sn-loc (sn-opnd loc sn))
  3216.          (opnds (touch-operands opnds '0 sn-loc)))
  3217.     (gen-div (car opnds) (cdr opnds) loc sn (any-contains-opnd? loc (cdr opnds))))))
  3218.  
  3219. (define-APPLY "##FIXNUM.REMAINDER" #f (lambda (opnds loc sn)
  3220.  
  3221.   (let* ((sn-loc (sn-opnd loc sn))
  3222.          (opnds (touch-operands opnds '0 sn-loc)))
  3223.     (gen-rem (car opnds) (cadr opnds) loc sn))))
  3224.  
  3225. (define-APPLY "##FIXNUM.MODULO" #f (lambda (opnds loc sn)
  3226.  
  3227.   (let* ((sn-loc (sn-opnd loc sn))
  3228.          (opnds (touch-operands opnds '0 sn-loc)))
  3229.     (gen-mod (car opnds) (cadr opnds) loc sn))))
  3230.  
  3231. (define-APPLY "##FIXNUM.LOGIOR" #f (lambda (opnds loc sn)
  3232.  
  3233.   (let* ((sn-loc (sn-opnd loc sn))
  3234.          (opnds (touch-operands opnds '0 sn-loc)))
  3235.     (cond ((null? opnds)
  3236.            (copy-opnd-to-loc (make-obj '0) loc sn))
  3237.           ((null? (cdr opnds))
  3238.            (copy-opnd-to-loc (car opnds) loc sn))
  3239.           ((or (reg? loc) (stk? loc))
  3240.            (commut-oper gen-logior opnds loc sn #f '() '()))
  3241.           (else
  3242.            (gen-logior opnds '() loc sn #f))))))
  3243.  
  3244. (define-APPLY "##FIXNUM.LOGXOR" #f (lambda (opnds loc sn)
  3245.  
  3246.   (let* ((sn-loc (sn-opnd loc sn))
  3247.          (opnds (touch-operands opnds '0 sn-loc)))
  3248.     (cond ((null? opnds)
  3249.            (copy-opnd-to-loc (make-obj '0) loc sn))
  3250.           ((null? (cdr opnds))
  3251.            (copy-opnd-to-loc (car opnds) loc sn))
  3252.           ((or (reg? loc) (stk? loc))
  3253.            (commut-oper gen-logxor opnds loc sn #f '() '()))
  3254.           (else
  3255.            (gen-logxor opnds '() loc sn #f))))))
  3256.  
  3257. (define-APPLY "##FIXNUM.LOGAND" #f (lambda (opnds loc sn)
  3258.  
  3259.   (let* ((sn-loc (sn-opnd loc sn))
  3260.          (opnds (touch-operands opnds '0 sn-loc)))
  3261.     (cond ((null? opnds)
  3262.            (copy-opnd-to-loc (make-obj '-1) loc sn))
  3263.           ((null? (cdr opnds))
  3264.            (copy-opnd-to-loc (car opnds) loc sn))
  3265.           ((or (reg? loc) (stk? loc))
  3266.            (commut-oper gen-logand opnds loc sn #f '() '()))
  3267.           (else
  3268.            (gen-logand opnds '() loc sn #f))))))
  3269.  
  3270. (define-APPLY "##FIXNUM.LOGNOT" #f (lambda (opnds loc sn)
  3271.  
  3272.   (let* ((sn-loc (sn-opnd loc sn))
  3273.          (opnd (car (touch-operands opnds '0 sn-loc))))
  3274.  
  3275.     (if (and (or (reg? loc) (stk? loc))
  3276.              (not (eq? loc return-reg)))
  3277.  
  3278.       (begin
  3279.         (copy-opnd-to-loc opnd loc sn-loc)
  3280.         (let ((loc68 (loc->loc68 loc #f sn)))
  3281.           (make-top-of-frame-if-stk-opnd68 loc68 sn)
  3282.           (emit-not.l (opnd68->true-opnd68 loc68 sn))
  3283.           (emit-and.w (make-imm -8) (opnd68->true-opnd68 loc68 sn))))
  3284.  
  3285.       (begin
  3286.         (move-opnd-to-loc68 opnd dtemp1 (sn-opnd loc sn))
  3287.         (emit-not.l dtemp1)
  3288.         (emit-and.w (make-imm -8) dtemp1)
  3289.         (move-opnd68-to-loc dtemp1 loc sn))))))
  3290.  
  3291. (define-APPLY "##FIXNUM.ASH" #f (gen-shift emit-asr.l))
  3292.  
  3293. (define-APPLY "##FIXNUM.LSH" #f (gen-shift emit-lsr.l))
  3294.  
  3295. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3296.  
  3297. (define-COND "##FIXNUM.ZERO?" (lambda (not? opnds lbl fs)
  3298.   (gen-eq-test 0 not? opnds lbl fs)))
  3299.  
  3300. (define-COND "##FIXNUM.POSITIVE?" (lambda (not? opnds lbl fs)
  3301.   (gen-compares emit-bgt emit-ble emit-blt emit-bge
  3302.                 not?
  3303.                 (list (touch-operand (car opnds) fs) (make-obj '0))
  3304.                 lbl
  3305.                 fs)))
  3306.  
  3307. (define-COND "##FIXNUM.NEGATIVE?" (lambda (not? opnds lbl fs)
  3308.   (gen-compares emit-blt emit-bge emit-bgt emit-ble
  3309.                 not?
  3310.                 (list (touch-operand (car opnds) fs) (make-obj '0))
  3311.                 lbl
  3312.                 fs)))
  3313.  
  3314. (define-COND "##FIXNUM.ODD?" (lambda (not? opnds lbl fs)
  3315.   (gen-even-test (not not?) opnds lbl fs)))
  3316.  
  3317. (define-COND "##FIXNUM.EVEN?" (lambda (not? opnds lbl fs)
  3318.   (gen-even-test not? opnds lbl fs)))
  3319.  
  3320. (define-COND "##FIXNUM.=" (lambda (not? opnds lbl fs)
  3321.   (gen-compares emit-beq emit-bne emit-beq emit-bne
  3322.                 not?
  3323.                 (touch-operands opnds '0 fs)
  3324.                 lbl
  3325.                 fs)))
  3326.  
  3327. (define-COND "##FIXNUM.<" (lambda (not? opnds lbl fs)
  3328.   (gen-compares emit-blt emit-bge emit-bgt emit-ble
  3329.                 not?
  3330.                 (touch-operands opnds '0 fs)
  3331.                 lbl
  3332.                 fs)))
  3333.  
  3334. (define-COND "##FIXNUM.>" (lambda (not? opnds lbl fs)
  3335.   (gen-compares emit-bgt emit-ble emit-blt emit-bge
  3336.                 not?
  3337.                 (touch-operands opnds '0 fs)
  3338.                 lbl
  3339.                 fs)))
  3340.  
  3341. (define-COND "##FIXNUM.<=" (lambda (not? opnds lbl fs)
  3342.   (gen-compares emit-ble emit-bgt emit-bge emit-blt
  3343.                 not?
  3344.                 (touch-operands opnds '0 fs)
  3345.                 lbl
  3346.                 fs)))
  3347.  
  3348. (define-COND "##FIXNUM.>=" (lambda (not? opnds lbl fs)
  3349.   (gen-compares emit-bge emit-blt emit-ble emit-bgt
  3350.                 not?
  3351.                 (touch-operands opnds '0 fs)
  3352.                 lbl
  3353.                 fs)))
  3354.  
  3355. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3356.  
  3357. (define-APPLY "##FLONUM.->FIXNUM" #f (lambda (opnds loc sn)
  3358.   (let* ((sn-loc (sn-opnd loc sn))
  3359.          (opnds (touch-operands opnds '0 sn-loc)))
  3360.     (move-opnd-to-loc68 (car opnds) atemp1 sn-loc)
  3361.     (let ((reg68 (if (and (reg? loc) (not (eq? loc return-reg)))
  3362.                    (reg->reg68 loc)
  3363.                    dtemp1)))
  3364.       (emit-fmov.d (make-disp* atemp1 (- pointer-size type-SUBTYPED)) ftemp1)
  3365.       (emit-fmov.l ftemp1 reg68)
  3366.       (emit-asl.l (make-imm 3) reg68)
  3367.       (if (not (and (reg? loc) (not (eq? loc return-reg))))
  3368.         (move-opnd68-to-loc reg68 loc sn))))))
  3369.  
  3370. (define-APPLY "##FLONUM.<-FIXNUM" #f (lambda (opnds loc sn)
  3371.   (gen-guarantee-space 4) ; make sure there is enough space for flonum
  3372.   (move-opnd-to-loc68 (car opnds) dtemp1 (sn-opnds (cdr opnds) (sn-opnd loc sn)))
  3373.   (emit-asr.l (make-imm 3) dtemp1)
  3374.   (emit-fmov.l dtemp1 ftemp1)
  3375.   (add-n-to-loc68 (* -4 pointer-size) heap-reg) ; allocate flonum
  3376.   (emit-move.l (make-imm (+ (* 2 1024) (* subtype-FLONUM 8)))
  3377.                (make-ind heap-reg))
  3378.   (let ((reg68 (if (reg? loc) (reg->reg68 loc) atemp1)))
  3379.     (emit-move.l heap-reg reg68)
  3380.     (emit-addq.l type-SUBTYPED reg68))
  3381.   (emit-fmov.d ftemp1 (make-disp* heap-reg pointer-size))
  3382.   (if (not (reg? loc))
  3383.     (move-opnd68-to-loc atemp1 loc sn))))
  3384.  
  3385. (define-APPLY "##FLONUM.+" #f (lambda (opnds loc sn)
  3386.  
  3387.   (let* ((sn-loc (sn-opnd loc sn))
  3388.          (opnds (touch-operands opnds '0 sn-loc)))
  3389.     (cond ((null? opnds)
  3390.            (copy-opnd-to-loc (make-obj inexact-0) loc sn))
  3391.           ((null? (cdr opnds))
  3392.            (copy-opnd-to-loc (car opnds) loc sn))
  3393.           (else
  3394.            (flo-oper emit-fmov.d emit-fadd.d opnds loc sn))))))
  3395.  
  3396. (define-APPLY "##FLONUM.-" #f (lambda (opnds loc sn)
  3397.  
  3398.   (let* ((sn-loc (sn-opnd loc sn))
  3399.          (opnds (touch-operands opnds '0 sn-loc)))
  3400.     (if (null? (cdr opnds))
  3401.       (flo-oper emit-fneg.d #f opnds loc sn)
  3402.       (flo-oper emit-fmov.d emit-fsub.d opnds loc sn)))))
  3403.  
  3404. (define-APPLY "##FLONUM.*" #f (lambda (opnds loc sn)
  3405.  
  3406.   (let* ((sn-loc (sn-opnd loc sn))
  3407.          (opnds (touch-operands opnds '0 sn-loc)))
  3408.     (cond ((null? opnds)
  3409.            (copy-opnd-to-loc (make-obj inexact-+1) loc sn))
  3410.           ((null? (cdr opnds))
  3411.            (copy-opnd-to-loc (car opnds) loc sn))
  3412.           (else
  3413.            (flo-oper emit-fmov.d emit-fmul.d opnds loc sn))))))
  3414.  
  3415. (define-APPLY "##FLONUM./" #f (lambda (opnds loc sn)
  3416.  
  3417.   (let* ((sn-loc (sn-opnd loc sn))
  3418.          (opnds (touch-operands opnds '0 sn-loc)))
  3419.     (if (null? (cdr opnds))
  3420.       (flo-oper emit-fmov.d emit-fdiv.d (cons (make-obj inexact-+1) opnds) loc sn)
  3421.       (flo-oper emit-fmov.d emit-fdiv.d opnds loc sn)))))
  3422.  
  3423. (define-APPLY "##FLONUM.ABS" #f (lambda (opnds loc sn)
  3424.   (let* ((sn-loc (sn-opnd loc sn))
  3425.          (opnds (touch-operands opnds '0 sn-loc)))
  3426.     (flo-oper emit-fabs.d #f opnds loc sn))))
  3427.  
  3428. (define-APPLY "##FLONUM.TRUNCATE" #f (lambda (opnds loc sn)
  3429.   (let* ((sn-loc (sn-opnd loc sn))
  3430.          (opnds (touch-operands opnds '0 sn-loc)))
  3431.     (flo-oper emit-fintrz.d #f opnds loc sn))))
  3432.  
  3433. (define-APPLY "##FLONUM.ROUND" #f (lambda (opnds loc sn)
  3434.   (let* ((sn-loc (sn-opnd loc sn))
  3435.          (opnds (touch-operands opnds '0 sn-loc)))
  3436.     (flo-oper emit-fint.d #f opnds loc sn))))
  3437.  
  3438. (define-APPLY "##FLONUM.EXP" #f (lambda (opnds loc sn)
  3439.   (let* ((sn-loc (sn-opnd loc sn))
  3440.          (opnds (touch-operands opnds '0 sn-loc)))
  3441.     (flo-oper emit-fetox.d #f opnds loc sn))))
  3442.  
  3443. (define-APPLY "##FLONUM.LOG" #f (lambda (opnds loc sn)
  3444.   (let* ((sn-loc (sn-opnd loc sn))
  3445.          (opnds (touch-operands opnds '0 sn-loc)))
  3446.     (flo-oper emit-flogn.d #f opnds loc sn))))
  3447.  
  3448. (define-APPLY "##FLONUM.SIN" #f (lambda (opnds loc sn)
  3449.   (let* ((sn-loc (sn-opnd loc sn))
  3450.          (opnds (touch-operands opnds '0 sn-loc)))
  3451.     (flo-oper emit-fsin.d #f opnds loc sn))))
  3452.  
  3453. (define-APPLY "##FLONUM.COS" #f (lambda (opnds loc sn)
  3454.   (let* ((sn-loc (sn-opnd loc sn))
  3455.          (opnds (touch-operands opnds '0 sn-loc)))
  3456.     (flo-oper emit-fcos.d #f opnds loc sn))))
  3457.  
  3458. (define-APPLY "##FLONUM.TAN" #f (lambda (opnds loc sn)
  3459.   (let* ((sn-loc (sn-opnd loc sn))
  3460.          (opnds (touch-operands opnds '0 sn-loc)))
  3461.     (flo-oper emit-ftan.d #f opnds loc sn))))
  3462.  
  3463. (define-APPLY "##FLONUM.ASIN" #f (lambda (opnds loc sn)
  3464.   (let* ((sn-loc (sn-opnd loc sn))
  3465.          (opnds (touch-operands opnds '0 sn-loc)))
  3466.     (flo-oper emit-fasin.d #f opnds loc sn))))
  3467.  
  3468. (define-APPLY "##FLONUM.ACOS" #f (lambda (opnds loc sn)
  3469.   (let* ((sn-loc (sn-opnd loc sn))
  3470.          (opnds (touch-operands opnds '0 sn-loc)))
  3471.     (flo-oper emit-facos.d #f opnds loc sn))))
  3472.  
  3473. (define-APPLY "##FLONUM.ATAN" #f (lambda (opnds loc sn)
  3474.   (let* ((sn-loc (sn-opnd loc sn))
  3475.          (opnds (touch-operands opnds '0 sn-loc)))
  3476.     (flo-oper emit-fatan.d #f opnds loc sn))))
  3477.  
  3478. (define-APPLY "##FLONUM.SQRT" #f (lambda (opnds loc sn)
  3479.   (let* ((sn-loc (sn-opnd loc sn))
  3480.          (opnds (touch-operands opnds '0 sn-loc)))
  3481.     (flo-oper emit-fsqrt.d #f opnds loc sn))))
  3482.  
  3483. (define-COND "##FLONUM.ZERO?" (lambda (not? opnds lbl fs)
  3484.   (gen-compares-flo emit-fbeq emit-fbne emit-fbeq emit-fbne
  3485.                     not?
  3486.                     (list (touch-operand (car opnds) fs) (make-obj inexact-0))
  3487.                     lbl
  3488.                     fs)))
  3489.  
  3490. (define-COND "##FLONUM.NEGATIVE?" (lambda (not? opnds lbl fs)
  3491.   (gen-compares-flo emit-fblt emit-fbge emit-fbgt emit-fble
  3492.                     not?
  3493.                     (list (touch-operand (car opnds) fs) (make-obj inexact-0))
  3494.                     lbl
  3495.                     fs)))
  3496.  
  3497. (define-COND "##FLONUM.POSITIVE?" (lambda (not? opnds lbl fs)
  3498.   (gen-compares-flo emit-fbgt emit-fble emit-fblt emit-fbge
  3499.                     not?
  3500.                     (list (touch-operand (car opnds) fs) (make-obj inexact-0))
  3501.                     lbl
  3502.                     fs)))
  3503.  
  3504. (define-COND "##FLONUM.=" (lambda (not? opnds lbl fs)
  3505.   (gen-compares-flo emit-fbeq emit-fbne emit-fbeq emit-fbne
  3506.                     not?
  3507.                     (touch-operands opnds '0 fs)
  3508.                     lbl
  3509.                     fs)))
  3510.  
  3511. (define-COND "##FLONUM.<" (lambda (not? opnds lbl fs)
  3512.   (gen-compares-flo emit-fblt emit-fbge emit-fbgt emit-fble
  3513.                     not?
  3514.                     (touch-operands opnds '0 fs)
  3515.                     lbl
  3516.                     fs)))
  3517.  
  3518. (define-COND "##FLONUM.>" (lambda (not? opnds lbl fs)
  3519.   (gen-compares-flo emit-fbgt emit-fble emit-fblt emit-fbge
  3520.                     not?
  3521.                     (touch-operands opnds '0 fs)
  3522.                     lbl
  3523.                     fs)))
  3524.  
  3525. (define-COND "##FLONUM.<=" (lambda (not? opnds lbl fs)
  3526.   (gen-compares-flo emit-fble emit-fbgt emit-fbge emit-fblt
  3527.                     not?
  3528.                     (touch-operands opnds '0 fs)
  3529.                     lbl
  3530.                     fs)))
  3531.  
  3532. (define-COND "##FLONUM.>=" (lambda (not? opnds lbl fs)
  3533.   (gen-compares-flo emit-fbge emit-fblt emit-fble emit-fbgt
  3534.                     not?
  3535.                     (touch-operands opnds '0 fs)
  3536.                     lbl
  3537.                     fs)))
  3538.  
  3539. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3540.  
  3541. (define-COND "##CHAR=?" (lambda (not? opnds lbl fs)
  3542.   (gen-compares emit-beq emit-bne emit-beq emit-bne
  3543.                 not?
  3544.                 (touch-operands opnds '0 fs)
  3545.                 lbl
  3546.                 fs)))
  3547.  
  3548. (define-COND "##CHAR<?" (lambda (not? opnds lbl fs)
  3549.   (gen-compares emit-blt emit-bge emit-bgt emit-ble
  3550.                 not?
  3551.                 (touch-operands opnds '0 fs)
  3552.                 lbl
  3553.                 fs)))
  3554.  
  3555. (define-COND "##CHAR>?" (lambda (not? opnds lbl fs)
  3556.   (gen-compares emit-bgt emit-ble emit-blt emit-bge
  3557.                 not?
  3558.                 (touch-operands opnds '0 fs)
  3559.                 lbl
  3560.                 fs)))
  3561.  
  3562. (define-COND "##CHAR<=?" (lambda (not? opnds lbl fs)
  3563.   (gen-compares emit-ble emit-bgt emit-bge emit-blt
  3564.                 not?
  3565.                 (touch-operands opnds '0 fs)
  3566.                 lbl
  3567.                 fs)))
  3568.  
  3569. (define-COND "##CHAR>=?" (lambda (not? opnds lbl fs)
  3570.   (gen-compares emit-bge emit-blt emit-ble emit-bgt
  3571.                 not?
  3572.                 (touch-operands opnds '0 fs)
  3573.                 lbl
  3574.                 fs)))
  3575.  
  3576. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3577.  
  3578. (define-APPLY "##CONS" #f (lambda (opnds loc sn)
  3579.   (gen-cons #f opnds loc sn)))
  3580.  
  3581. (define-APPLY "##SET-CAR!" #t (lambda (opnds loc sn)
  3582.   (gen-set-car! #f opnds loc sn)))
  3583.  
  3584. (define-APPLY "##SET-CDR!" #t (lambda (opnds loc sn)
  3585.   (gen-set-cdr! #f opnds loc sn)))
  3586.  
  3587. (define-APPLY "##CAR"    #f (make-gen-APPLY-C...R #f 2))
  3588. (define-APPLY "##CDR"    #f (make-gen-APPLY-C...R #f 3))
  3589. (define-APPLY "##CAAR"   #f (make-gen-APPLY-C...R #f 4))
  3590. (define-APPLY "##CADR"   #f (make-gen-APPLY-C...R #f 5))
  3591. (define-APPLY "##CDAR"   #f (make-gen-APPLY-C...R #f 6))
  3592. (define-APPLY "##CDDR"   #f (make-gen-APPLY-C...R #f 7))
  3593. (define-APPLY "##CAAAR"  #f (make-gen-APPLY-C...R #f 8))
  3594. (define-APPLY "##CAADR"  #f (make-gen-APPLY-C...R #f 9))
  3595. (define-APPLY "##CADAR"  #f (make-gen-APPLY-C...R #f 10))
  3596. (define-APPLY "##CADDR"  #f (make-gen-APPLY-C...R #f 11))
  3597. (define-APPLY "##CDAAR"  #f (make-gen-APPLY-C...R #f 12))
  3598. (define-APPLY "##CDADR"  #f (make-gen-APPLY-C...R #f 13))
  3599. (define-APPLY "##CDDAR"  #f (make-gen-APPLY-C...R #f 14))
  3600. (define-APPLY "##CDDDR"  #f (make-gen-APPLY-C...R #f 15))
  3601. (define-APPLY "##CAAAAR" #f (make-gen-APPLY-C...R #f 16))
  3602. (define-APPLY "##CAAADR" #f (make-gen-APPLY-C...R #f 17))
  3603. (define-APPLY "##CAADAR" #f (make-gen-APPLY-C...R #f 18))
  3604. (define-APPLY "##CAADDR" #f (make-gen-APPLY-C...R #f 19))
  3605. (define-APPLY "##CADAAR" #f (make-gen-APPLY-C...R #f 20))
  3606. (define-APPLY "##CADADR" #f (make-gen-APPLY-C...R #f 21))
  3607. (define-APPLY "##CADDAR" #f (make-gen-APPLY-C...R #f 22))
  3608. (define-APPLY "##CADDDR" #f (make-gen-APPLY-C...R #f 23))
  3609. (define-APPLY "##CDAAAR" #f (make-gen-APPLY-C...R #f 24))
  3610. (define-APPLY "##CDAADR" #f (make-gen-APPLY-C...R #f 25))
  3611. (define-APPLY "##CDADAR" #f (make-gen-APPLY-C...R #f 26))
  3612. (define-APPLY "##CDADDR" #f (make-gen-APPLY-C...R #f 27))
  3613. (define-APPLY "##CDDAAR" #f (make-gen-APPLY-C...R #f 28))
  3614. (define-APPLY "##CDDADR" #f (make-gen-APPLY-C...R #f 29))
  3615. (define-APPLY "##CDDDAR" #f (make-gen-APPLY-C...R #f 30))
  3616. (define-APPLY "##CDDDDR" #f (make-gen-APPLY-C...R #f 31))
  3617.  
  3618. (define-APPLY "##WEAK-CONS" #f (lambda (opnds loc sn)
  3619.   (gen-cons #t opnds loc sn)))
  3620.  
  3621. (define-APPLY "##WEAK-SET-CAR!" #t (lambda (opnds loc sn)
  3622.   (gen-set-car! #t opnds loc sn)))
  3623.  
  3624. (define-APPLY "##WEAK-SET-CDR!" #t (lambda (opnds loc sn)
  3625.   (gen-set-cdr! #t opnds loc sn)))
  3626.  
  3627. (define-APPLY "##WEAK-CAR" #f (make-gen-APPLY-C...R #t 2))
  3628. (define-APPLY "##WEAK-CDR" #f (make-gen-APPLY-C...R #t 3))
  3629.  
  3630. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3631.  
  3632. (define-APPLY "##MAKE-CELL" #f (lambda (opnds loc sn)
  3633.   (gen-cons #f (list (car opnds) (make-obj '())) loc sn)))
  3634.  
  3635. (define-APPLY "##CELL-REF" #f (make-gen-APPLY-C...R #f 2))
  3636.  
  3637. (define-APPLY "##CELL-SET!" #t (lambda (opnds loc sn)
  3638.   (gen-set-car! #f opnds loc sn)))
  3639.  
  3640. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3641.  
  3642. (define-APPLY "##VECTOR"           #f (gen-vector 'VECTOR))
  3643. (define-APPLY "##VECTOR-LENGTH"    #f (gen-vector-length 'VECTOR))
  3644. (define-APPLY "##VECTOR-REF"       #f (gen-vector-ref 'VECTOR))
  3645. (define-APPLY "##VECTOR-SET!"      #t (gen-vector-set! 'VECTOR))
  3646. (define-APPLY "##VECTOR-SHRINK!"   #t (gen-vector-shrink! 'VECTOR))
  3647.  
  3648. (define-APPLY "##STRING"           #f (gen-vector 'STRING))
  3649. (define-APPLY "##STRING-LENGTH"    #f (gen-vector-length 'STRING))
  3650. (define-APPLY "##STRING-REF"       #f (gen-vector-ref 'STRING))
  3651. (define-APPLY "##STRING-SET!"      #t (gen-vector-set! 'STRING))
  3652. (define-APPLY "##STRING-SHRINK!"   #t (gen-vector-shrink! 'STRING))
  3653.  
  3654. (define-APPLY "##VECTOR8"          #f (gen-vector 'VECTOR8))
  3655. (define-APPLY "##VECTOR8-LENGTH"   #f (gen-vector-length 'VECTOR8))
  3656. (define-APPLY "##VECTOR8-REF"      #f (gen-vector-ref 'VECTOR8))
  3657. (define-APPLY "##VECTOR8-SET!"     #t (gen-vector-set! 'VECTOR8))
  3658. (define-APPLY "##VECTOR8-SHRINK!"  #t (gen-vector-shrink! 'VECTOR8))
  3659.  
  3660. (define-APPLY "##VECTOR16"         #f (gen-vector 'VECTOR16))
  3661. (define-APPLY "##VECTOR16-LENGTH"  #f (gen-vector-length 'VECTOR16))
  3662. (define-APPLY "##VECTOR16-REF"     #f (gen-vector-ref 'VECTOR16))
  3663. (define-APPLY "##VECTOR16-SET!"    #t (gen-vector-set! 'VECTOR16))
  3664. (define-APPLY "##VECTOR16-SHRINK!" #t (gen-vector-shrink! 'VECTOR16))
  3665.  
  3666. (define-APPLY "##SLOT-REF"         #f (gen-vector-ref 'SLOT))
  3667. (define-APPLY "##SLOT-SET!"        #t (gen-vector-set! 'SLOT))
  3668.  
  3669. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3670.  
  3671. (define-APPLY "##PSTATE" #f (lambda (opnds loc sn)
  3672.   (move-opnd68-to-loc pstate-reg loc sn)))
  3673.  
  3674. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3675.  
  3676. (define-APPLY "##TOUCH" #t (lambda (opnds loc sn)
  3677.   (let ((opnd (car opnds)))
  3678.     (let ((opnd* (if (and (not (pot-fut? opnd))
  3679.                           (not (lbl? opnd))
  3680.                           (not (obj? opnd)))
  3681.                    (put-pot-fut opnd)
  3682.                    opnd)))
  3683.       (if loc
  3684.         (touch-opnd-to-loc opnd* loc sn)
  3685.         (touch-opnd-to-any-reg68 opnd* #f sn))))))
  3686.  
  3687. ;------------------------------------------------------------------------------
  3688.  
  3689. (def-spec "NOT"        (safe "##NOT"))
  3690. (def-spec "NULL?"      (safe "##NULL?"))
  3691. (def-spec "EQ?"        (safe "##EQ?"))
  3692.  
  3693. (def-spec "PAIR?"      (safe "##PAIR?"))
  3694. (def-spec "PROCEDURE?" (safe "##PROCEDURE?"))
  3695. (def-spec "VECTOR?"    (safe "##VECTOR?"))
  3696. (def-spec "SYMBOL?"    (safe "##SYMBOL?"))
  3697. (def-spec "STRING?"    (safe "##STRING?"))
  3698. (def-spec "CHAR?"      (safe "##CHAR?"))
  3699.  
  3700. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3701.  
  3702. (def-spec "ZERO?"     (safe-arith   "##FIXNUM.ZERO?"     "##FLONUM.ZERO?"))
  3703. (def-spec "POSITIVE?" (safe-arith   "##FIXNUM.POSITIVE?" "##FLONUM.POSITIVE?"))
  3704. (def-spec "NEGATIVE?" (safe-arith   "##FIXNUM.NEGATIVE?" "##FLONUM.NEGATIVE?"))
  3705. (def-spec "ODD?"      (safe-arith   "##FIXNUM.ODD?"      #f))
  3706. (def-spec "EVEN?"     (safe-arith   "##FIXNUM.EVEN?"     #f))
  3707.  
  3708. (def-spec "+"         (unsafe-arith "##FIXNUM.+"         "##FLONUM.+"))
  3709. (def-spec "*"         (unsafe-arith "##FIXNUM.*"         "##FLONUM.*"))
  3710. (def-spec "-"         (unsafe-arith "##FIXNUM.-"         "##FLONUM.-"))
  3711. (def-spec "/"         (unsafe-arith #f                   "##FLONUM./"))
  3712. (def-spec "QUOTIENT"  (unsafe-arith "##FIXNUM.QUOTIENT"  #f))
  3713. (def-spec "REMAINDER" (unsafe-arith "##FIXNUM.REMAINDER" #f))
  3714. (def-spec "MODULO"    (unsafe-arith "##FIXNUM.MODULO"    #f))
  3715.  
  3716. (def-spec "##LOGIOR"  (unsafe-arith "##FIXNUM.LOGIOR"    #f))
  3717. (def-spec "##LOGXOR"  (unsafe-arith "##FIXNUM.LOGXOR"    #f))
  3718. (def-spec "##LOGAND"  (unsafe-arith "##FIXNUM.LOGAND"    #f))
  3719. (def-spec "##LOGNOT"  (unsafe-arith "##FIXNUM.LOGNOT"    #f))
  3720. (def-spec "##ASH"     (unsafe-arith "##FIXNUM.ASH"       #f))
  3721.  
  3722. (def-spec "="         (safe-arith   "##FIXNUM.="         "##FLONUM.="))
  3723. (def-spec "<"         (safe-arith   "##FIXNUM.<"         "##FLONUM.<"))
  3724. (def-spec ">"         (safe-arith   "##FIXNUM.>"         "##FLONUM.>"))
  3725. (def-spec "<="        (safe-arith   "##FIXNUM.<="        "##FLONUM.<="))
  3726. (def-spec ">="        (safe-arith   "##FIXNUM.>="        "##FLONUM.>="))
  3727.  
  3728. (def-spec "ABS"       (unsafe-arith #f                   "##FLONUM.ABS"))
  3729. (def-spec "TRUNCATE"  (unsafe-arith #f                   "##FLONUM.TRUNCATE"))
  3730. (def-spec "EXP"       (unsafe-arith #f                   "##FLONUM.EXP"))
  3731. (def-spec "LOG"       (unsafe-arith #f                   "##FLONUM.LOG"))
  3732. (def-spec "SIN"       (unsafe-arith #f                   "##FLONUM.SIN"))
  3733. (def-spec "COS"       (unsafe-arith #f                   "##FLONUM.COS"))
  3734. (def-spec "TAN"       (unsafe-arith #f                   "##FLONUM.TAN"))
  3735. (def-spec "ASIN"      (unsafe-arith #f                   "##FLONUM.ASIN"))
  3736. (def-spec "ACOS"      (unsafe-arith #f                   "##FLONUM.ACOS"))
  3737. (def-spec "ATAN"      (unsafe-arith #f                   "##FLONUM.ATAN"))
  3738. (def-spec "SQRT"      (unsafe-arith #f                   "##FLONUM.SQRT"))
  3739.  
  3740. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3741.  
  3742. (def-spec "CHAR=?"    (safe "##CHAR=?"))
  3743. (def-spec "CHAR<?"    (safe "##CHAR<?"))
  3744. (def-spec "CHAR>?"    (safe "##CHAR>?"))
  3745. (def-spec "CHAR<=?"   (safe "##CHAR<=?"))
  3746. (def-spec "CHAR>=?"   (safe "##CHAR>=?"))
  3747.  
  3748. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3749.  
  3750. (def-spec "CONS"             (safe "##CONS"))
  3751. (def-spec "SET-CAR!"         (unsafe "##SET-CAR!"))
  3752. (def-spec "SET-CDR!"         (unsafe "##SET-CDR!"))
  3753. (def-spec "CAR"              (unsafe "##CAR"))
  3754. (def-spec "CDR"              (unsafe "##CDR"))
  3755. (def-spec "CAAR"             (unsafe "##CAAR"))
  3756. (def-spec "CADR"             (unsafe "##CADR"))
  3757. (def-spec "CDAR"             (unsafe "##CDAR"))
  3758. (def-spec "CDDR"             (unsafe "##CDDR"))
  3759. (def-spec "CAAAR"            (unsafe "##CAAAR"))
  3760. (def-spec "CAADR"            (unsafe "##CAADR"))
  3761. (def-spec "CADAR"            (unsafe "##CADAR"))
  3762. (def-spec "CADDR"            (unsafe "##CADDR"))
  3763. (def-spec "CDAAR"            (unsafe "##CDAAR"))
  3764. (def-spec "CDADR"            (unsafe "##CDADR"))
  3765. (def-spec "CDDAR"            (unsafe "##CDDAR"))
  3766. (def-spec "CDDDR"            (unsafe "##CDDDR"))
  3767. (def-spec "CAAAAR"           (unsafe "##CAAAAR"))
  3768. (def-spec "CAAADR"           (unsafe "##CAAADR"))
  3769. (def-spec "CAADAR"           (unsafe "##CAADAR"))
  3770. (def-spec "CAADDR"           (unsafe "##CAADDR"))
  3771. (def-spec "CADAAR"           (unsafe "##CADAAR"))
  3772. (def-spec "CADADR"           (unsafe "##CADADR"))
  3773. (def-spec "CADDAR"           (unsafe "##CADDAR"))
  3774. (def-spec "CADDDR"           (unsafe "##CADDDR"))
  3775. (def-spec "CDAAAR"           (unsafe "##CDAAAR"))
  3776. (def-spec "CDAADR"           (unsafe "##CDAADR"))
  3777. (def-spec "CDADAR"           (unsafe "##CDADAR"))
  3778. (def-spec "CDADDR"           (unsafe "##CDADDR"))
  3779. (def-spec "CDDAAR"           (unsafe "##CDDAAR"))
  3780. (def-spec "CDDADR"           (unsafe "##CDDADR"))
  3781. (def-spec "CDDDAR"           (unsafe "##CDDDAR"))
  3782. (def-spec "CDDDDR"           (unsafe "##CDDDDR"))
  3783.  
  3784. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3785.  
  3786. (def-spec "VECTOR"           (safe "##VECTOR"))
  3787. (def-spec "VECTOR-LENGTH"    (unsafe "##VECTOR-LENGTH"))
  3788. (def-spec "VECTOR-REF"       (unsafe "##VECTOR-REF"))
  3789. (def-spec "VECTOR-SET!"      (unsafe "##VECTOR-SET!"))
  3790.  
  3791. (def-spec "STRING"           (safe "##STRING"))
  3792. (def-spec "STRING-LENGTH"    (unsafe "##STRING-LENGTH"))
  3793. (def-spec "STRING-REF"       (unsafe "##STRING-REF"))
  3794. (def-spec "STRING-SET!"      (unsafe "##STRING-SET!"))
  3795.  
  3796. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3797.  
  3798. (def-spec "TOUCH"            (safe "##TOUCH"))
  3799.  
  3800. ;------------------------------------------------------------------------------
  3801.  
  3802. (let ((targ (make-target 3 'M68000)))
  3803.  
  3804.   (target-begin!-set! targ (lambda (info-port) (begin! info-port targ)))
  3805.  
  3806.   (put-target targ))
  3807.  
  3808. ;==============================================================================
  3809.